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 * This is the AST frontend library.
22 * The AST frontend library is not a frontend on it's own but provides a
23 * generic abstract syntax tree (AST) abstraction for HDL code and can be
24 * used by HDL frontends. See "ast.h" for an overview of the API and the
25 * Verilog frontend for an usage example.
29 #include "kernel/log.h"
30 #include "libs/sha1/sha1.h"
31 #include "frontends/verilog/verilog_frontend.h"
42 using namespace AST_INTERNAL
;
44 // convert the AST into a simpler AST that has all parameters substituted by their
45 // values, unrolled for-loops, expanded generate blocks, etc. when this function
46 // is done with an AST it can be converted into RTLIL using genRTLIL().
48 // this function also does all name resolving and sets the id2ast member of all
49 // nodes that link to a different node using names and lexical scoping.
50 bool AstNode::simplify(bool const_fold
, bool at_zero
, bool in_lvalue
, int stage
, int width_hint
, bool sign_hint
, bool in_param
)
52 static int recursion_counter
= 0;
53 static pair
<string
, int> last_blocking_assignment_warn
;
54 static bool deep_recursion_warning
= false;
56 if (recursion_counter
++ == 1000 && deep_recursion_warning
) {
57 log_warning("Deep recursion in AST simplifier.\nDoes this design contain insanely long expressions?\n");
58 deep_recursion_warning
= false;
61 AstNode
*newNode
= NULL
;
62 bool did_something
= false;
65 log("-------------\n");
66 log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage
, recursion_counter
, filename
.c_str(), linenum
, type2str(type
).c_str(), this);
67 log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
68 int(const_fold
), int(at_zero
), int(in_lvalue
), int(stage
), int(width_hint
), int(sign_hint
), int(in_param
));
69 // dumpAst(NULL, "> ");
74 log_assert(type
== AST_MODULE
);
75 last_blocking_assignment_warn
= pair
<string
, int>();
77 deep_recursion_warning
= true;
78 while (simplify(const_fold
, at_zero
, in_lvalue
, 1, width_hint
, sign_hint
, in_param
)) { }
80 if (!flag_nomem2reg
&& !get_bool_attribute("\\nomem2reg"))
82 dict
<AstNode
*, pool
<std::string
>> mem2reg_places
;
83 dict
<AstNode
*, uint32_t> mem2reg_candidates
, dummy_proc_flags
;
84 uint32_t flags
= flag_mem2reg
? AstNode::MEM2REG_FL_ALL
: 0;
85 mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, dummy_proc_flags
, flags
);
87 pool
<AstNode
*> mem2reg_set
;
88 for (auto &it
: mem2reg_candidates
)
90 AstNode
*mem
= it
.first
;
91 uint32_t memflags
= it
.second
;
92 bool this_nomeminit
= flag_nomeminit
;
93 log_assert((memflags
& ~0x00ffff00) == 0);
95 if (mem
->get_bool_attribute("\\nomem2reg"))
98 if (mem
->get_bool_attribute("\\nomeminit") || get_bool_attribute("\\nomeminit"))
99 this_nomeminit
= true;
101 if (memflags
& AstNode::MEM2REG_FL_FORCED
)
102 goto silent_activate
;
104 if (memflags
& AstNode::MEM2REG_FL_EQ2
)
105 goto verbose_activate
;
107 if (memflags
& AstNode::MEM2REG_FL_SET_ASYNC
)
108 goto verbose_activate
;
110 if ((memflags
& AstNode::MEM2REG_FL_SET_INIT
) && (memflags
& AstNode::MEM2REG_FL_SET_ELSE
) && this_nomeminit
)
111 goto verbose_activate
;
113 if (memflags
& AstNode::MEM2REG_FL_CMPLX_LHS
)
114 goto verbose_activate
;
116 // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
120 if (mem2reg_set
.count(mem
) == 0) {
121 std::string message
= stringf("Replacing memory %s with list of registers.", mem
->str
.c_str());
122 bool first_element
= true;
123 for (auto &place
: mem2reg_places
[it
.first
]) {
124 message
+= stringf("%s%s", first_element
? " See " : ", ", place
.c_str());
125 first_element
= false;
127 log_warning("%s\n", message
.c_str());
131 // log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
132 mem2reg_set
.insert(mem
);
135 for (auto node
: mem2reg_set
)
137 int mem_width
, mem_size
, addr_bits
;
138 node
->meminfo(mem_width
, mem_size
, addr_bits
);
140 for (int i
= 0; i
< mem_size
; i
++) {
141 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
142 mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
143 reg
->str
= stringf("%s[%d]", node
->str
.c_str(), i
);
145 reg
->is_signed
= node
->is_signed
;
146 children
.push_back(reg
);
147 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
151 AstNode
*async_block
= NULL
;
152 while (mem2reg_as_needed_pass2(mem2reg_set
, this, NULL
, async_block
)) { }
154 vector
<AstNode
*> delnodes
;
155 mem2reg_remove(mem2reg_set
, delnodes
);
157 for (auto node
: delnodes
)
161 while (simplify(const_fold
, at_zero
, in_lvalue
, 2, width_hint
, sign_hint
, in_param
)) { }
166 current_filename
= filename
;
167 set_line_num(linenum
);
169 // we do not look inside a task or function
170 // (but as soon as a task or function is instantiated we process the generated AST as usual)
171 if (type
== AST_FUNCTION
|| type
== AST_TASK
) {
176 // deactivate all calls to non-synthesis system tasks
177 // note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
178 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && (str
== "$strobe" || str
== "$monitor" || str
== "$time" ||
179 str
== "$dumpfile" || str
== "$dumpvars" || str
== "$dumpon" || str
== "$dumpoff" || str
== "$dumpall")) {
180 log_warning("Ignoring call to system %s %s at %s:%d.\n", type
== AST_FCALL
? "function" : "task", str
.c_str(), filename
.c_str(), linenum
);
185 if ((type
== AST_TCALL
) && (str
== "$display" || str
== "$write") && (!current_always
|| current_always
->type
!= AST_INITIAL
)) {
186 log_warning("System task `%s' outside initial block is unsupported at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
191 // print messages if this a call to $display() or $write()
192 // This code implements only a small subset of Verilog-2005 $display() format specifiers,
193 // but should be good enough for most uses
194 if ((type
== AST_TCALL
) && ((str
== "$display") || (str
== "$write")))
196 int nargs
= GetSize(children
);
198 log_error("System task `%s' got %d arguments, expected >= 1 at %s:%d.\n",
199 str
.c_str(), int(children
.size()), filename
.c_str(), linenum
);
201 // First argument is the format string
202 AstNode
*node_string
= children
[0];
203 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
204 if (node_string
->type
!= AST_CONSTANT
)
205 log_error("Failed to evaluate system task `%s' with non-constant 1st argument at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
206 std::string sformat
= node_string
->bitsAsConst().decode_string();
208 // Other arguments are placeholders. Process the string as we go through it
211 for (size_t i
= 0; i
< sformat
.length(); i
++)
214 if (sformat
[i
] == '%')
216 // If there's no next character, that's a problem
217 if (i
+1 >= sformat
.length())
218 log_error("System task `%s' called with `%%' at end of string at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
220 char cformat
= sformat
[++i
];
222 // %% is special, does not need a matching argument
229 // Simplify the argument
230 AstNode
*node_arg
= nullptr;
232 // Everything from here on depends on the format specifier
241 if (next_arg
>= GetSize(children
))
242 log_error("Missing argument for %%%c format specifier in system task `%s' at %s:%d.\n",
243 cformat
, str
.c_str(), filename
.c_str(), linenum
);
245 node_arg
= children
[next_arg
++];
246 while (node_arg
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
247 if (node_arg
->type
!= AST_CONSTANT
)
248 log_error("Failed to evaluate system task `%s' with non-constant argument at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
256 log_error("System task `%s' called with invalid/unsupported format specifier at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
264 sout
+= node_arg
->bitsAsConst().decode_string();
271 snprintf(tmp
, sizeof(tmp
), "%d", node_arg
->bitsAsConst().as_int());
280 snprintf(tmp
, sizeof(tmp
), "%x", node_arg
->bitsAsConst().as_int());
287 sout
+= log_id(current_module
->name
);
295 // not a format specifier
300 // Finally, print the message (only include a \n for $display, not for $write)
301 log("%s", sout
.c_str());
302 if (str
== "$display")
308 // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
309 if (type
== AST_WIRE
|| type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_RANGE
|| type
== AST_PREFIX
)
311 if (type
== AST_IDENTIFIER
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
))
314 // in certain cases a function must be evaluated constant. this is what in_param controls.
315 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_PREFIX
)
318 std::map
<std::string
, AstNode
*> backup_scope
;
320 // create name resolution entries for all objects with names
321 // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
322 if (type
== AST_MODULE
) {
323 current_scope
.clear();
324 std::map
<std::string
, AstNode
*> this_wire_scope
;
325 for (size_t i
= 0; i
< children
.size(); i
++) {
326 AstNode
*node
= children
[i
];
327 if (node
->type
== AST_WIRE
) {
328 if (this_wire_scope
.count(node
->str
) > 0) {
329 AstNode
*first_node
= this_wire_scope
[node
->str
];
330 if (!node
->is_input
&& !node
->is_output
&& node
->is_reg
&& node
->children
.size() == 0)
331 goto wires_are_compatible
;
332 if (first_node
->children
.size() == 0 && node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
333 AstNode
*r
= node
->children
[0];
334 if (r
->range_valid
&& r
->range_left
== 0 && r
->range_right
== 0) {
336 node
->children
.pop_back();
339 if (first_node
->children
.size() != node
->children
.size())
340 goto wires_are_incompatible
;
341 for (size_t j
= 0; j
< node
->children
.size(); j
++) {
342 AstNode
*n1
= first_node
->children
[j
], *n2
= node
->children
[j
];
343 if (n1
->type
== AST_RANGE
&& n2
->type
== AST_RANGE
&& n1
->range_valid
&& n2
->range_valid
) {
344 if (n1
->range_left
!= n2
->range_left
)
345 goto wires_are_incompatible
;
346 if (n1
->range_right
!= n2
->range_right
)
347 goto wires_are_incompatible
;
348 } else if (*n1
!= *n2
)
349 goto wires_are_incompatible
;
351 if (first_node
->range_left
!= node
->range_left
)
352 goto wires_are_incompatible
;
353 if (first_node
->range_right
!= node
->range_right
)
354 goto wires_are_incompatible
;
355 if (first_node
->port_id
== 0 && (node
->is_input
|| node
->is_output
))
356 goto wires_are_incompatible
;
357 wires_are_compatible
:
359 first_node
->is_input
= true;
361 first_node
->is_output
= true;
363 first_node
->is_reg
= true;
365 first_node
->is_signed
= true;
366 for (auto &it
: node
->attributes
) {
367 if (first_node
->attributes
.count(it
.first
) > 0)
368 delete first_node
->attributes
[it
.first
];
369 first_node
->attributes
[it
.first
] = it
.second
->clone();
371 children
.erase(children
.begin()+(i
--));
372 did_something
= true;
375 wires_are_incompatible
:
377 log_error("Incompatible re-declaration of wire %s at %s:%d.\n", node
->str
.c_str(), filename
.c_str(), linenum
);
380 this_wire_scope
[node
->str
] = node
;
382 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
383 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
|| node
->type
== AST_CELL
) {
384 backup_scope
[node
->str
] = current_scope
[node
->str
];
385 current_scope
[node
->str
] = node
;
388 for (size_t i
= 0; i
< children
.size(); i
++) {
389 AstNode
*node
= children
[i
];
390 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_MEMORY
)
391 while (node
->simplify(true, false, false, 1, -1, false, node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
))
392 did_something
= true;
396 auto backup_current_block
= current_block
;
397 auto backup_current_block_child
= current_block_child
;
398 auto backup_current_top_block
= current_top_block
;
399 auto backup_current_always
= current_always
;
400 auto backup_current_always_clocked
= current_always_clocked
;
402 if (type
== AST_ALWAYS
|| type
== AST_INITIAL
)
404 current_always
= this;
405 current_always_clocked
= false;
407 if (type
== AST_ALWAYS
)
408 for (auto child
: children
) {
409 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
410 current_always_clocked
= true;
411 if (child
->type
== AST_EDGE
&& GetSize(child
->children
) == 1 &&
412 child
->children
[0]->type
== AST_IDENTIFIER
&& child
->children
[0]->str
== "\\$global_clock")
413 current_always_clocked
= true;
417 int backup_width_hint
= width_hint
;
418 bool backup_sign_hint
= sign_hint
;
420 bool detect_width_simple
= false;
421 bool child_0_is_self_determined
= false;
422 bool child_1_is_self_determined
= false;
423 bool child_2_is_self_determined
= false;
424 bool children_are_self_determined
= false;
425 bool reset_width_after_children
= false;
432 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, true, stage
, -1, false, in_param
) == true)
433 did_something
= true;
434 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
) == true)
435 did_something
= true;
436 children
[0]->detectSignWidth(backup_width_hint
, backup_sign_hint
);
437 children
[1]->detectSignWidth(width_hint
, sign_hint
);
438 width_hint
= max(width_hint
, backup_width_hint
);
439 child_0_is_self_determined
= true;
444 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, true) == true)
445 did_something
= true;
446 children
[0]->detectSignWidth(width_hint
, sign_hint
);
447 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
448 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, true) == true)
449 did_something
= true;
450 if (!children
[1]->range_valid
)
451 log_error("Non-constant width range on parameter decl at %s:%d.\n", filename
.c_str(), linenum
);
452 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
458 case AST_TO_UNSIGNED
:
464 case AST_REDUCE_XNOR
:
465 case AST_REDUCE_BOOL
:
466 detect_width_simple
= true;
467 children_are_self_determined
= true;
482 detect_width_simple
= true;
486 case AST_SHIFT_RIGHT
:
487 case AST_SHIFT_SLEFT
:
488 case AST_SHIFT_SRIGHT
:
490 detect_width_simple
= true;
491 child_1_is_self_determined
= true;
504 for (auto child
: children
) {
505 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
506 did_something
= true;
507 child
->detectSignWidthWorker(width_hint
, sign_hint
);
509 reset_width_after_children
= true;
515 detect_width_simple
= true;
516 children_are_self_determined
= true;
520 detect_width_simple
= true;
521 child_0_is_self_determined
= true;
525 detect_width_simple
= true;
526 children_are_self_determined
= true;
531 children_are_self_determined
= true;
539 if (detect_width_simple
&& width_hint
< 0) {
540 if (type
== AST_REPLICATE
)
541 while (children
[0]->simplify(true, false, in_lvalue
, stage
, -1, false, true) == true)
542 did_something
= true;
543 for (auto child
: children
)
544 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
545 did_something
= true;
546 detectSignWidth(width_hint
, sign_hint
);
549 if (type
== AST_FCALL
&& str
== "\\$past")
550 detectSignWidth(width_hint
, sign_hint
);
552 if (type
== AST_TERNARY
) {
553 int width_hint_left
, width_hint_right
;
554 bool sign_hint_left
, sign_hint_right
;
555 bool found_real_left
, found_real_right
;
556 children
[1]->detectSignWidth(width_hint_left
, sign_hint_left
, &found_real_left
);
557 children
[2]->detectSignWidth(width_hint_right
, sign_hint_right
, &found_real_right
);
558 if (found_real_left
|| found_real_right
) {
559 child_1_is_self_determined
= true;
560 child_2_is_self_determined
= true;
564 if (type
== AST_CONDX
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
565 for (auto &bit
: children
.at(0)->bits
)
566 if (bit
== State::Sz
|| bit
== State::Sx
)
570 if (type
== AST_CONDZ
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
571 for (auto &bit
: children
.at(0)->bits
)
572 if (bit
== State::Sz
)
576 if (const_fold
&& type
== AST_CASE
)
578 while (children
[0]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
579 if (children
[0]->type
== AST_CONSTANT
&& children
[0]->bits_only_01()) {
580 std::vector
<AstNode
*> new_children
;
581 new_children
.push_back(children
[0]);
582 for (int i
= 1; i
< GetSize(children
); i
++) {
583 AstNode
*child
= children
[i
];
584 log_assert(child
->type
== AST_COND
|| child
->type
== AST_CONDX
|| child
->type
== AST_CONDZ
);
585 for (auto v
: child
->children
) {
586 if (v
->type
== AST_DEFAULT
)
587 goto keep_const_cond
;
588 if (v
->type
== AST_BLOCK
)
590 while (v
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
591 if (v
->type
== AST_CONSTANT
&& v
->bits_only_01()) {
592 if (v
->bits
== children
[0]->bits
) {
593 while (i
+1 < GetSize(children
))
594 delete children
[++i
];
595 goto keep_const_cond
;
599 goto keep_const_cond
;
603 new_children
.push_back(child
);
607 new_children
.swap(children
);
611 // simplify all children first
612 // (iterate by index as e.g. auto wires can add new children in the process)
613 for (size_t i
= 0; i
< children
.size(); i
++) {
614 bool did_something_here
= true;
615 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && i
>= 3)
617 if ((type
== AST_GENIF
|| type
== AST_GENCASE
) && i
>= 1)
619 if (type
== AST_GENBLOCK
)
621 if (type
== AST_BLOCK
&& !str
.empty())
623 if (type
== AST_PREFIX
&& i
>= 1)
625 while (did_something_here
&& i
< children
.size()) {
626 bool const_fold_here
= const_fold
, in_lvalue_here
= in_lvalue
;
627 int width_hint_here
= width_hint
;
628 bool sign_hint_here
= sign_hint
;
629 bool in_param_here
= in_param
;
630 if (i
== 0 && (type
== AST_REPLICATE
|| type
== AST_WIRE
))
631 const_fold_here
= true, in_param_here
= true;
632 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
)
633 const_fold_here
= true;
634 if (i
== 0 && (type
== AST_ASSIGN
|| type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
))
635 in_lvalue_here
= true;
636 if (type
== AST_BLOCK
) {
637 current_block
= this;
638 current_block_child
= children
[i
];
640 if ((type
== AST_ALWAYS
|| type
== AST_INITIAL
) && children
[i
]->type
== AST_BLOCK
)
641 current_top_block
= children
[i
];
642 if (i
== 0 && child_0_is_self_determined
)
643 width_hint_here
= -1, sign_hint_here
= false;
644 if (i
== 1 && child_1_is_self_determined
)
645 width_hint_here
= -1, sign_hint_here
= false;
646 if (i
== 2 && child_2_is_self_determined
)
647 width_hint_here
= -1, sign_hint_here
= false;
648 if (children_are_self_determined
)
649 width_hint_here
= -1, sign_hint_here
= false;
650 did_something_here
= children
[i
]->simplify(const_fold_here
, at_zero
, in_lvalue_here
, stage
, width_hint_here
, sign_hint_here
, in_param_here
);
651 if (did_something_here
)
652 did_something
= true;
654 if (stage
== 2 && children
[i
]->type
== AST_INITIAL
&& current_ast_mod
!= this) {
655 current_ast_mod
->children
.push_back(children
[i
]);
656 children
.erase(children
.begin() + (i
--));
657 did_something
= true;
660 for (auto &attr
: attributes
) {
661 while (attr
.second
->simplify(true, false, false, stage
, -1, false, true))
662 did_something
= true;
665 if (reset_width_after_children
) {
666 width_hint
= backup_width_hint
;
667 sign_hint
= backup_sign_hint
;
669 detectSignWidth(width_hint
, sign_hint
);
672 current_block
= backup_current_block
;
673 current_block_child
= backup_current_block_child
;
674 current_top_block
= backup_current_top_block
;
675 current_always
= backup_current_always
;
676 current_always_clocked
= backup_current_always_clocked
;
678 for (auto it
= backup_scope
.begin(); it
!= backup_scope
.end(); it
++) {
679 if (it
->second
== NULL
)
680 current_scope
.erase(it
->first
);
682 current_scope
[it
->first
] = it
->second
;
685 current_filename
= filename
;
686 set_line_num(linenum
);
688 if (type
== AST_MODULE
)
689 current_scope
.clear();
691 // convert defparam nodes to cell parameters
692 if (type
== AST_DEFPARAM
&& !children
.empty())
694 if (children
[0]->type
!= AST_IDENTIFIER
)
695 log_error("Module name in defparam at %s:%d contains non-constant expressions!\n", filename
.c_str(), linenum
);
697 string modname
, paramname
= children
[0]->str
;
699 size_t pos
= paramname
.rfind('.');
701 while (pos
!= 0 && pos
!= std::string::npos
)
703 modname
= paramname
.substr(0, pos
);
705 if (current_scope
.count(modname
))
708 pos
= paramname
.rfind('.', pos
- 1);
711 if (pos
== std::string::npos
)
712 log_error("Can't find object for defparam `%s` at %s:%d!\n", RTLIL::unescape_id(paramname
).c_str(), filename
.c_str(), linenum
);
714 paramname
= "\\" + paramname
.substr(pos
+1);
716 if (current_scope
.at(modname
)->type
!= AST_CELL
)
717 log_error("Defparam argument `%s . %s` does not match a cell at %s:%d!\n",
718 RTLIL::unescape_id(modname
).c_str(), RTLIL::unescape_id(paramname
).c_str(), filename
.c_str(), linenum
);
720 AstNode
*paraset
= new AstNode(AST_PARASET
, children
[1]->clone(), GetSize(children
) > 2 ? children
[2]->clone() : NULL
);
721 paraset
->str
= paramname
;
723 AstNode
*cell
= current_scope
.at(modname
);
724 cell
->children
.insert(cell
->children
.begin() + 1, paraset
);
728 // resolve constant prefixes
729 if (type
== AST_PREFIX
) {
730 if (children
[0]->type
!= AST_CONSTANT
) {
731 // dumpAst(NULL, "> ");
732 log_error("Index in generate block prefix syntax at %s:%d is not constant!\n", filename
.c_str(), linenum
);
734 if (children
[1]->type
== AST_PREFIX
)
735 children
[1]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
);
736 log_assert(children
[1]->type
== AST_IDENTIFIER
);
737 newNode
= children
[1]->clone();
738 const char *second_part
= children
[1]->str
.c_str();
739 if (second_part
[0] == '\\')
741 newNode
->str
= stringf("%s[%d].%s", str
.c_str(), children
[0]->integer
, second_part
);
745 // evaluate TO_BITS nodes
746 if (type
== AST_TO_BITS
) {
747 if (children
[0]->type
!= AST_CONSTANT
)
748 log_error("Left operand of to_bits expression is not constant at %s:%d!\n", filename
.c_str(), linenum
);
749 if (children
[1]->type
!= AST_CONSTANT
)
750 log_error("Right operand of to_bits expression is not constant at %s:%d!\n", filename
.c_str(), linenum
);
751 RTLIL::Const new_value
= children
[1]->bitsAsConst(children
[0]->bitsAsConst().as_int(), children
[1]->is_signed
);
752 newNode
= mkconst_bits(new_value
.bits
, children
[1]->is_signed
);
756 // annotate constant ranges
757 if (type
== AST_RANGE
) {
758 bool old_range_valid
= range_valid
;
760 range_swapped
= false;
763 log_assert(children
.size() >= 1);
764 if (children
[0]->type
== AST_CONSTANT
) {
766 range_left
= children
[0]->integer
;
767 if (children
.size() == 1)
768 range_right
= range_left
;
770 if (children
.size() >= 2) {
771 if (children
[1]->type
== AST_CONSTANT
)
772 range_right
= children
[1]->integer
;
776 if (old_range_valid
!= range_valid
)
777 did_something
= true;
778 if (range_valid
&& range_left
>= 0 && range_right
> range_left
) {
779 int tmp
= range_right
;
780 range_right
= range_left
;
782 range_swapped
= true;
786 // annotate wires with their ranges
787 if (type
== AST_WIRE
) {
788 if (children
.size() > 0) {
789 if (children
[0]->range_valid
) {
791 did_something
= true;
793 range_swapped
= children
[0]->range_swapped
;
794 range_left
= children
[0]->range_left
;
795 range_right
= children
[0]->range_right
;
799 did_something
= true;
801 range_swapped
= false;
807 // resolve multiranges on memory decl
808 if (type
== AST_MEMORY
&& children
.size() > 1 && children
[1]->type
== AST_MULTIRANGE
)
811 multirange_dimensions
.clear();
812 for (auto range
: children
[1]->children
) {
813 if (!range
->range_valid
)
814 log_error("Non-constant range on memory decl at %s:%d.\n", filename
.c_str(), linenum
);
815 multirange_dimensions
.push_back(min(range
->range_left
, range
->range_right
));
816 multirange_dimensions
.push_back(max(range
->range_left
, range
->range_right
) - min(range
->range_left
, range
->range_right
) + 1);
817 total_size
*= multirange_dimensions
.back();
820 children
[1] = new AstNode(AST_RANGE
, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size
-1, true));
821 did_something
= true;
824 // resolve multiranges on memory access
825 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
&& children
.size() > 0 && children
[0]->type
== AST_MULTIRANGE
)
827 AstNode
*index_expr
= nullptr;
829 for (int i
= 0; 2*i
< GetSize(id2ast
->multirange_dimensions
); i
++)
831 if (GetSize(children
[0]->children
) < i
)
832 log_error("Insufficient number of array indices for %s at %s:%d.\n", log_id(str
), filename
.c_str(), linenum
);
834 AstNode
*new_index_expr
= children
[0]->children
[i
]->children
.at(0)->clone();
836 if (id2ast
->multirange_dimensions
[2*i
])
837 new_index_expr
= new AstNode(AST_SUB
, new_index_expr
, AstNode::mkconst_int(id2ast
->multirange_dimensions
[2*i
], true));
840 index_expr
= new_index_expr
;
842 index_expr
= new AstNode(AST_ADD
, new AstNode(AST_MUL
, index_expr
, AstNode::mkconst_int(id2ast
->multirange_dimensions
[2*i
+1], true)), new_index_expr
);
845 for (int i
= GetSize(id2ast
->multirange_dimensions
)/2; i
< GetSize(children
[0]->children
); i
++)
846 children
.push_back(children
[0]->children
[i
]->clone());
849 if (index_expr
== nullptr)
850 children
.erase(children
.begin());
852 children
[0] = new AstNode(AST_RANGE
, index_expr
);
854 did_something
= true;
857 // trim/extend parameters
858 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
) {
859 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
860 if (!children
[1]->range_valid
)
861 log_error("Non-constant width range on parameter decl at %s:%d.\n", filename
.c_str(), linenum
);
862 int width
= std::abs(children
[1]->range_left
- children
[1]->range_right
) + 1;
863 if (children
[0]->type
== AST_REALVALUE
) {
864 RTLIL::Const constvalue
= children
[0]->realAsConst(width
);
865 log_warning("converting real value %e to binary %s at %s:%d.\n",
866 children
[0]->realvalue
, log_signal(constvalue
), filename
.c_str(), linenum
);
868 children
[0] = mkconst_bits(constvalue
.bits
, sign_hint
);
869 did_something
= true;
871 if (children
[0]->type
== AST_CONSTANT
) {
872 if (width
!= int(children
[0]->bits
.size())) {
873 RTLIL::SigSpec
sig(children
[0]->bits
);
874 sig
.extend_u0(width
, children
[0]->is_signed
);
875 AstNode
*old_child_0
= children
[0];
876 children
[0] = mkconst_bits(sig
.as_const().bits
, is_signed
);
879 children
[0]->is_signed
= is_signed
;
882 range_swapped
= children
[1]->range_swapped
;
883 range_left
= children
[1]->range_left
;
884 range_right
= children
[1]->range_right
;
886 if (children
.size() > 1 && children
[1]->type
== AST_REALVALUE
&& children
[0]->type
== AST_CONSTANT
) {
887 double as_realvalue
= children
[0]->asReal(sign_hint
);
889 children
[0] = new AstNode(AST_REALVALUE
);
890 children
[0]->realvalue
= as_realvalue
;
891 did_something
= true;
895 // annotate identifiers using scope resolution and create auto-wires as needed
896 if (type
== AST_IDENTIFIER
) {
897 if (current_scope
.count(str
) == 0) {
898 for (auto node
: current_ast_mod
->children
) {
899 if ((node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
900 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
) && str
== node
->str
) {
901 current_scope
[node
->str
] = node
;
906 if (current_scope
.count(str
) == 0) {
907 // log_warning("Creating auto-wire `%s' in module `%s'.\n", str.c_str(), current_ast_mod->str.c_str());
908 AstNode
*auto_wire
= new AstNode(AST_AUTOWIRE
);
909 auto_wire
->str
= str
;
910 current_ast_mod
->children
.push_back(auto_wire
);
911 current_scope
[str
] = auto_wire
;
912 did_something
= true;
914 if (id2ast
!= current_scope
[str
]) {
915 id2ast
= current_scope
[str
];
916 did_something
= true;
920 // split memory access with bit select to individual statements
921 if (type
== AST_IDENTIFIER
&& children
.size() == 2 && children
[0]->type
== AST_RANGE
&& children
[1]->type
== AST_RANGE
&& !in_lvalue
)
923 if (id2ast
== NULL
|| id2ast
->type
!= AST_MEMORY
|| children
[0]->children
.size() != 1)
924 log_error("Invalid bit-select on memory access at %s:%d!\n", filename
.c_str(), linenum
);
926 int mem_width
, mem_size
, addr_bits
;
927 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
929 int data_range_left
= id2ast
->children
[0]->range_left
;
930 int data_range_right
= id2ast
->children
[0]->range_right
;
932 std::stringstream sstr
;
933 sstr
<< "$mem2bits$" << str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
934 std::string wire_id
= sstr
.str();
936 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
939 wire
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
940 current_ast_mod
->children
.push_back(wire
);
941 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
943 AstNode
*data
= clone();
944 delete data
->children
[1];
945 data
->children
.pop_back();
947 AstNode
*assign
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), data
);
948 assign
->children
[0]->str
= wire_id
;
952 size_t assign_idx
= 0;
953 while (assign_idx
< current_block
->children
.size() && current_block
->children
[assign_idx
] != current_block_child
)
955 log_assert(assign_idx
< current_block
->children
.size());
956 current_block
->children
.insert(current_block
->children
.begin()+assign_idx
, assign
);
961 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
962 proc
->children
[0]->children
.push_back(assign
);
963 current_ast_mod
->children
.push_back(proc
);
966 newNode
= new AstNode(AST_IDENTIFIER
, children
[1]->clone());
967 newNode
->str
= wire_id
;
968 newNode
->id2ast
= wire
;
972 if (type
== AST_WHILE
)
973 log_error("While loops are only allowed in constant functions at %s:%d!\n", filename
.c_str(), linenum
);
975 if (type
== AST_REPEAT
)
976 log_error("Repeat loops are only allowed in constant functions at %s:%d!\n", filename
.c_str(), linenum
);
978 // unroll for loops and generate-for blocks
979 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && children
.size() != 0)
981 AstNode
*init_ast
= children
[0];
982 AstNode
*while_ast
= children
[1];
983 AstNode
*next_ast
= children
[2];
984 AstNode
*body_ast
= children
[3];
986 while (body_ast
->type
== AST_GENBLOCK
&& body_ast
->str
.empty() &&
987 body_ast
->children
.size() == 1 && body_ast
->children
.at(0)->type
== AST_GENBLOCK
)
988 body_ast
= body_ast
->children
.at(0);
990 if (init_ast
->type
!= AST_ASSIGN_EQ
)
991 log_error("Unsupported 1st expression of generate for-loop at %s:%d!\n", filename
.c_str(), linenum
);
992 if (next_ast
->type
!= AST_ASSIGN_EQ
)
993 log_error("Unsupported 3rd expression of generate for-loop at %s:%d!\n", filename
.c_str(), linenum
);
995 if (type
== AST_GENFOR
) {
996 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
997 log_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a gen var!\n", filename
.c_str(), linenum
);
998 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
999 log_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a gen var!\n", filename
.c_str(), linenum
);
1001 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1002 log_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a register!\n", filename
.c_str(), linenum
);
1003 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1004 log_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a register!\n", filename
.c_str(), linenum
);
1007 if (init_ast
->children
[0]->id2ast
!= next_ast
->children
[0]->id2ast
)
1008 log_error("Incompatible left-hand sides in 1st and 3rd expression of generate for-loop at %s:%d!\n", filename
.c_str(), linenum
);
1010 // eval 1st expression
1011 AstNode
*varbuf
= init_ast
->children
[1]->clone();
1012 while (varbuf
->simplify(true, false, false, stage
, 32, true, false)) { }
1014 if (varbuf
->type
!= AST_CONSTANT
)
1015 log_error("Right hand side of 1st expression of generate for-loop at %s:%d is not constant!\n", filename
.c_str(), linenum
);
1017 varbuf
= new AstNode(AST_LOCALPARAM
, varbuf
);
1018 varbuf
->str
= init_ast
->children
[0]->str
;
1020 AstNode
*backup_scope_varbuf
= current_scope
[varbuf
->str
];
1021 current_scope
[varbuf
->str
] = varbuf
;
1023 size_t current_block_idx
= 0;
1024 if (type
== AST_FOR
) {
1025 while (current_block_idx
< current_block
->children
.size() &&
1026 current_block
->children
[current_block_idx
] != current_block_child
)
1027 current_block_idx
++;
1032 // eval 2nd expression
1033 AstNode
*buf
= while_ast
->clone();
1034 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1036 if (buf
->type
!= AST_CONSTANT
)
1037 log_error("2nd expression of generate for-loop at %s:%d is not constant!\n", filename
.c_str(), linenum
);
1039 if (buf
->integer
== 0) {
1046 int index
= varbuf
->children
[0]->integer
;
1047 if (body_ast
->type
== AST_GENBLOCK
)
1048 buf
= body_ast
->clone();
1050 buf
= new AstNode(AST_GENBLOCK
, body_ast
->clone());
1051 if (buf
->str
.empty()) {
1052 std::stringstream sstr
;
1053 sstr
<< "$genblock$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1054 buf
->str
= sstr
.str();
1056 std::map
<std::string
, std::string
> name_map
;
1057 std::stringstream sstr
;
1058 sstr
<< buf
->str
<< "[" << index
<< "].";
1059 buf
->expand_genblock(varbuf
->str
, sstr
.str(), name_map
);
1061 if (type
== AST_GENFOR
) {
1062 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1063 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1064 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1067 for (size_t i
= 0; i
< buf
->children
.size(); i
++)
1068 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
->children
[i
]);
1070 buf
->children
.clear();
1073 // eval 3rd expression
1074 buf
= next_ast
->children
[1]->clone();
1075 while (buf
->simplify(true, false, false, stage
, 32, true, false)) { }
1077 if (buf
->type
!= AST_CONSTANT
)
1078 log_error("Right hand side of 3rd expression of generate for-loop at %s:%d is not constant!\n", filename
.c_str(), linenum
);
1080 delete varbuf
->children
[0];
1081 varbuf
->children
[0] = buf
;
1084 current_scope
[varbuf
->str
] = backup_scope_varbuf
;
1087 did_something
= true;
1090 // check for local objects in unnamed block
1091 if (type
== AST_BLOCK
&& str
.empty())
1093 for (size_t i
= 0; i
< children
.size(); i
++)
1094 if (children
[i
]->type
== AST_WIRE
|| children
[i
]->type
== AST_MEMORY
|| children
[i
]->type
== AST_PARAMETER
|| children
[i
]->type
== AST_LOCALPARAM
)
1095 log_error("Local declaration in unnamed block at %s:%d is an unsupported SystemVerilog feature!\n",
1096 children
[i
]->filename
.c_str(), children
[i
]->linenum
);
1099 // transform block with name
1100 if (type
== AST_BLOCK
&& !str
.empty())
1102 std::map
<std::string
, std::string
> name_map
;
1103 expand_genblock(std::string(), str
+ ".", name_map
);
1105 std::vector
<AstNode
*> new_children
;
1106 for (size_t i
= 0; i
< children
.size(); i
++)
1107 if (children
[i
]->type
== AST_WIRE
|| children
[i
]->type
== AST_MEMORY
|| children
[i
]->type
== AST_PARAMETER
|| children
[i
]->type
== AST_LOCALPARAM
) {
1108 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1109 current_ast_mod
->children
.push_back(children
[i
]);
1110 current_scope
[children
[i
]->str
] = children
[i
];
1112 new_children
.push_back(children
[i
]);
1114 children
.swap(new_children
);
1115 did_something
= true;
1119 // simplify unconditional generate block
1120 if (type
== AST_GENBLOCK
&& children
.size() != 0)
1123 std::map
<std::string
, std::string
> name_map
;
1124 expand_genblock(std::string(), str
+ ".", name_map
);
1127 for (size_t i
= 0; i
< children
.size(); i
++) {
1128 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1129 current_ast_mod
->children
.push_back(children
[i
]);
1133 did_something
= true;
1136 // simplify generate-if blocks
1137 if (type
== AST_GENIF
&& children
.size() != 0)
1139 AstNode
*buf
= children
[0]->clone();
1140 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1141 if (buf
->type
!= AST_CONSTANT
) {
1142 // for (auto f : log_files)
1143 // dumpAst(f, "verilog-ast> ");
1144 log_error("Condition for generate if at %s:%d is not constant!\n", filename
.c_str(), linenum
);
1146 if (buf
->asBool() != 0) {
1148 buf
= children
[1]->clone();
1151 buf
= children
.size() > 2 ? children
[2]->clone() : NULL
;
1156 if (buf
->type
!= AST_GENBLOCK
)
1157 buf
= new AstNode(AST_GENBLOCK
, buf
);
1159 if (!buf
->str
.empty()) {
1160 std::map
<std::string
, std::string
> name_map
;
1161 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1164 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1165 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1166 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1169 buf
->children
.clear();
1174 did_something
= true;
1177 // simplify generate-case blocks
1178 if (type
== AST_GENCASE
&& children
.size() != 0)
1180 AstNode
*buf
= children
[0]->clone();
1181 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1182 if (buf
->type
!= AST_CONSTANT
) {
1183 // for (auto f : log_files)
1184 // dumpAst(f, "verilog-ast> ");
1185 log_error("Condition for generate case at %s:%d is not constant!\n", filename
.c_str(), linenum
);
1188 bool ref_signed
= buf
->is_signed
;
1189 RTLIL::Const ref_value
= buf
->bitsAsConst();
1192 AstNode
*selected_case
= NULL
;
1193 for (size_t i
= 1; i
< children
.size(); i
++)
1195 log_assert(children
.at(i
)->type
== AST_COND
|| children
.at(i
)->type
== AST_CONDX
|| children
.at(i
)->type
== AST_CONDZ
);
1197 AstNode
*this_genblock
= NULL
;
1198 for (auto child
: children
.at(i
)->children
) {
1199 log_assert(this_genblock
== NULL
);
1200 if (child
->type
== AST_GENBLOCK
)
1201 this_genblock
= child
;
1204 for (auto child
: children
.at(i
)->children
)
1206 if (child
->type
== AST_DEFAULT
) {
1207 if (selected_case
== NULL
)
1208 selected_case
= this_genblock
;
1211 if (child
->type
== AST_GENBLOCK
)
1214 buf
= child
->clone();
1215 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1216 if (buf
->type
!= AST_CONSTANT
) {
1217 // for (auto f : log_files)
1218 // dumpAst(f, "verilog-ast> ");
1219 log_error("Expression in generate case at %s:%d is not constant!\n", filename
.c_str(), linenum
);
1222 bool is_selected
= RTLIL::const_eq(ref_value
, buf
->bitsAsConst(), ref_signed
&& buf
->is_signed
, ref_signed
&& buf
->is_signed
, 1).as_bool();
1226 selected_case
= this_genblock
;
1227 i
= children
.size();
1233 if (selected_case
!= NULL
)
1235 log_assert(selected_case
->type
== AST_GENBLOCK
);
1236 buf
= selected_case
->clone();
1238 if (!buf
->str
.empty()) {
1239 std::map
<std::string
, std::string
> name_map
;
1240 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1243 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1244 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1245 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1248 buf
->children
.clear();
1253 did_something
= true;
1256 // unroll cell arrays
1257 if (type
== AST_CELLARRAY
)
1259 if (!children
.at(0)->range_valid
)
1260 log_error("Non-constant array range on cell array at %s:%d.\n", filename
.c_str(), linenum
);
1262 newNode
= new AstNode(AST_GENBLOCK
);
1263 int num
= max(children
.at(0)->range_left
, children
.at(0)->range_right
) - min(children
.at(0)->range_left
, children
.at(0)->range_right
) + 1;
1265 for (int i
= 0; i
< num
; i
++) {
1266 int idx
= children
.at(0)->range_left
> children
.at(0)->range_right
? children
.at(0)->range_right
+ i
: children
.at(0)->range_right
- i
;
1267 AstNode
*new_cell
= children
.at(1)->clone();
1268 newNode
->children
.push_back(new_cell
);
1269 new_cell
->str
+= stringf("[%d]", idx
);
1270 if (new_cell
->type
== AST_PRIMITIVE
) {
1271 log_error("Cell arrays of primitives are currently not supported at %s:%d.\n", filename
.c_str(), linenum
);
1273 log_assert(new_cell
->children
.at(0)->type
== AST_CELLTYPE
);
1274 new_cell
->children
.at(0)->str
= stringf("$array:%d:%d:%s", i
, num
, new_cell
->children
.at(0)->str
.c_str());
1281 // replace primitives with assignments
1282 if (type
== AST_PRIMITIVE
)
1284 if (children
.size() < 2)
1285 log_error("Insufficient number of arguments for primitive `%s' at %s:%d!\n",
1286 str
.c_str(), filename
.c_str(), linenum
);
1288 std::vector
<AstNode
*> children_list
;
1289 for (auto child
: children
) {
1290 log_assert(child
->type
== AST_ARGUMENT
);
1291 log_assert(child
->children
.size() == 1);
1292 children_list
.push_back(child
->children
[0]);
1293 child
->children
.clear();
1298 if (str
== "bufif0" || str
== "bufif1" || str
== "notif0" || str
== "notif1")
1300 if (children_list
.size() != 3)
1301 log_error("Invalid number of arguments for primitive `%s' at %s:%d!\n",
1302 str
.c_str(), filename
.c_str(), linenum
);
1304 std::vector
<RTLIL::State
> z_const(1, RTLIL::State::Sz
);
1306 AstNode
*mux_input
= children_list
.at(1);
1307 if (str
== "notif0" || str
== "notif1") {
1308 mux_input
= new AstNode(AST_BIT_NOT
, mux_input
);
1310 AstNode
*node
= new AstNode(AST_TERNARY
, children_list
.at(2));
1311 if (str
== "bufif0") {
1312 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1313 node
->children
.push_back(mux_input
);
1315 node
->children
.push_back(mux_input
);
1316 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1321 children
.push_back(children_list
.at(0));
1322 children
.push_back(node
);
1323 did_something
= true;
1327 AstNodeType op_type
= AST_NONE
;
1328 bool invert_results
= false;
1331 op_type
= AST_BIT_AND
;
1333 op_type
= AST_BIT_AND
, invert_results
= true;
1335 op_type
= AST_BIT_OR
;
1337 op_type
= AST_BIT_OR
, invert_results
= true;
1339 op_type
= AST_BIT_XOR
;
1341 op_type
= AST_BIT_XOR
, invert_results
= true;
1345 op_type
= AST_POS
, invert_results
= true;
1346 log_assert(op_type
!= AST_NONE
);
1348 AstNode
*node
= children_list
[1];
1349 if (op_type
!= AST_POS
)
1350 for (size_t i
= 2; i
< children_list
.size(); i
++)
1351 node
= new AstNode(op_type
, node
, children_list
[i
]);
1353 node
= new AstNode(AST_BIT_NOT
, node
);
1357 children
.push_back(children_list
[0]);
1358 children
.push_back(node
);
1359 did_something
= true;
1363 // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
1364 // a big case block that selects the correct single-bit assignment.
1365 if (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) {
1366 if (children
[0]->type
!= AST_IDENTIFIER
|| children
[0]->children
.size() == 0)
1367 goto skip_dynamic_range_lvalue_expansion
;
1368 if (children
[0]->children
[0]->range_valid
|| did_something
)
1369 goto skip_dynamic_range_lvalue_expansion
;
1370 if (children
[0]->id2ast
== NULL
|| children
[0]->id2ast
->type
!= AST_WIRE
)
1371 goto skip_dynamic_range_lvalue_expansion
;
1372 if (!children
[0]->id2ast
->range_valid
)
1373 goto skip_dynamic_range_lvalue_expansion
;
1374 int source_width
= children
[0]->id2ast
->range_left
- children
[0]->id2ast
->range_right
+ 1;
1375 int result_width
= 1;
1376 AstNode
*shift_expr
= NULL
;
1377 AstNode
*range
= children
[0]->children
[0];
1378 if (range
->children
.size() == 1) {
1379 shift_expr
= range
->children
[0]->clone();
1381 shift_expr
= range
->children
[1]->clone();
1382 AstNode
*left_at_zero_ast
= range
->children
[0]->clone();
1383 AstNode
*right_at_zero_ast
= range
->children
[1]->clone();
1384 while (left_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1385 while (right_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1386 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
1387 log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
1388 str
.c_str(), filename
.c_str(), linenum
);
1389 result_width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
1391 did_something
= true;
1392 newNode
= new AstNode(AST_CASE
, shift_expr
);
1393 for (int i
= 0; i
<= source_width
-result_width
; i
++) {
1394 int start_bit
= children
[0]->id2ast
->range_right
+ i
;
1395 AstNode
*cond
= new AstNode(AST_COND
, mkconst_int(start_bit
, true));
1396 AstNode
*lvalue
= children
[0]->clone();
1397 lvalue
->delete_children();
1398 lvalue
->children
.push_back(new AstNode(AST_RANGE
,
1399 mkconst_int(start_bit
+result_width
-1, true), mkconst_int(start_bit
, true)));
1400 cond
->children
.push_back(new AstNode(AST_BLOCK
, new AstNode(type
, lvalue
, children
[1]->clone())));
1401 newNode
->children
.push_back(cond
);
1405 skip_dynamic_range_lvalue_expansion
:;
1407 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && current_block
!= NULL
)
1409 std::stringstream sstr
;
1410 sstr
<< "$formal$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1411 std::string id_check
= sstr
.str() + "_CHECK", id_en
= sstr
.str() + "_EN";
1413 AstNode
*wire_check
= new AstNode(AST_WIRE
);
1414 wire_check
->str
= id_check
;
1415 current_ast_mod
->children
.push_back(wire_check
);
1416 current_scope
[wire_check
->str
] = wire_check
;
1417 while (wire_check
->simplify(true, false, false, 1, -1, false, false)) { }
1419 AstNode
*wire_en
= new AstNode(AST_WIRE
);
1420 wire_en
->str
= id_en
;
1421 current_ast_mod
->children
.push_back(wire_en
);
1422 if (current_always_clocked
) {
1423 current_ast_mod
->children
.push_back(new AstNode(AST_INITIAL
, new AstNode(AST_BLOCK
, new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), AstNode::mkconst_int(0, false, 1)))));
1424 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->str
= id_en
;
1426 current_scope
[wire_en
->str
] = wire_en
;
1427 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
1429 std::vector
<RTLIL::State
> x_bit
;
1430 x_bit
.push_back(RTLIL::State::Sx
);
1432 AstNode
*assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bit
, false));
1433 assign_check
->children
[0]->str
= id_check
;
1435 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, 1));
1436 assign_en
->children
[0]->str
= id_en
;
1438 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
1439 default_signals
->children
.push_back(assign_check
);
1440 default_signals
->children
.push_back(assign_en
);
1441 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
1443 assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_REDUCE_BOOL
, children
[0]->clone()));
1444 assign_check
->children
[0]->str
= id_check
;
1446 if (current_always
== nullptr || current_always
->type
!= AST_INITIAL
) {
1447 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(1, false, 1));
1449 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_FCALL
));
1450 assign_en
->children
[1]->str
= "\\$initstate";
1452 assign_en
->children
[0]->str
= id_en
;
1454 newNode
= new AstNode(AST_BLOCK
);
1455 newNode
->children
.push_back(assign_check
);
1456 newNode
->children
.push_back(assign_en
);
1458 AstNode
*assertnode
= new AstNode(type
);
1459 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1460 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1461 assertnode
->children
[0]->str
= id_check
;
1462 assertnode
->children
[1]->str
= id_en
;
1463 assertnode
->attributes
.swap(attributes
);
1464 current_ast_mod
->children
.push_back(assertnode
);
1469 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && children
.size() == 1)
1471 children
.push_back(mkconst_int(1, false, 1));
1472 did_something
= true;
1475 // found right-hand side identifier for memory -> replace with memory read port
1476 if (stage
> 1 && type
== AST_IDENTIFIER
&& id2ast
!= NULL
&& id2ast
->type
== AST_MEMORY
&& !in_lvalue
&&
1477 children
.size() == 1 && children
[0]->type
== AST_RANGE
&& children
[0]->children
.size() == 1) {
1478 newNode
= new AstNode(AST_MEMRD
, children
[0]->children
[0]->clone());
1480 newNode
->id2ast
= id2ast
;
1484 // assignment with nontrivial member in left-hand concat expression -> split assignment
1485 if ((type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_CONCAT
&& width_hint
> 0)
1487 bool found_nontrivial_member
= false;
1489 for (auto child
: children
[0]->children
) {
1490 if (child
->type
== AST_IDENTIFIER
&& child
->id2ast
!= NULL
&& child
->id2ast
->type
== AST_MEMORY
)
1491 found_nontrivial_member
= true;
1494 if (found_nontrivial_member
)
1496 newNode
= new AstNode(AST_BLOCK
);
1498 AstNode
*wire_tmp
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
1499 wire_tmp
->str
= stringf("$splitcmplxassign$%s:%d$%d", filename
.c_str(), linenum
, autoidx
++);
1500 current_ast_mod
->children
.push_back(wire_tmp
);
1501 current_scope
[wire_tmp
->str
] = wire_tmp
;
1502 wire_tmp
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
1503 while (wire_tmp
->simplify(true, false, false, 1, -1, false, false)) { }
1505 AstNode
*wire_tmp_id
= new AstNode(AST_IDENTIFIER
);
1506 wire_tmp_id
->str
= wire_tmp
->str
;
1508 newNode
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, wire_tmp_id
, children
[1]->clone()));
1511 for (auto child
: children
[0]->children
)
1513 int child_width_hint
= -1;
1514 bool child_sign_hint
= true;
1515 child
->detectSignWidth(child_width_hint
, child_sign_hint
);
1517 AstNode
*rhs
= wire_tmp_id
->clone();
1518 rhs
->children
.push_back(new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+child_width_hint
-1, true), AstNode::mkconst_int(cursor
, true)));
1519 newNode
->children
.push_back(new AstNode(type
, child
->clone(), rhs
));
1521 cursor
+= child_width_hint
;
1528 // assignment with memory in left-hand side expression -> replace with memory write port
1529 if (stage
> 1 && (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_IDENTIFIER
&&
1530 children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
&& children
[0]->id2ast
->children
.size() >= 2 &&
1531 children
[0]->id2ast
->children
[0]->range_valid
&& children
[0]->id2ast
->children
[1]->range_valid
&&
1532 (children
[0]->children
.size() == 1 || children
[0]->children
.size() == 2) && children
[0]->children
[0]->type
== AST_RANGE
)
1534 std::stringstream sstr
;
1535 sstr
<< "$memwr$" << children
[0]->str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1536 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA", id_en
= sstr
.str() + "_EN";
1538 if (type
== AST_ASSIGN_EQ
) {
1539 pair
<string
, int> this_blocking_assignment_warn(filename
, linenum
);
1540 if (this_blocking_assignment_warn
!= last_blocking_assignment_warn
)
1541 log_warning("Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n",
1542 filename
.c_str(), linenum
);
1543 last_blocking_assignment_warn
= this_blocking_assignment_warn
;
1546 int mem_width
, mem_size
, addr_bits
;
1547 bool mem_signed
= children
[0]->id2ast
->is_signed
;
1548 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
1550 int data_range_left
= children
[0]->id2ast
->children
[0]->range_left
;
1551 int data_range_right
= children
[0]->id2ast
->children
[0]->range_right
;
1552 int mem_data_range_offset
= std::min(data_range_left
, data_range_right
);
1554 int addr_width_hint
= -1;
1555 bool addr_sign_hint
= true;
1556 children
[0]->children
[0]->children
[0]->detectSignWidthWorker(addr_width_hint
, addr_sign_hint
);
1557 addr_bits
= std::max(addr_bits
, addr_width_hint
);
1559 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
1560 wire_addr
->str
= id_addr
;
1561 current_ast_mod
->children
.push_back(wire_addr
);
1562 current_scope
[wire_addr
->str
] = wire_addr
;
1563 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
1565 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
1566 wire_data
->str
= id_data
;
1567 wire_data
->is_signed
= mem_signed
;
1568 current_ast_mod
->children
.push_back(wire_data
);
1569 current_scope
[wire_data
->str
] = wire_data
;
1570 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
1572 AstNode
*wire_en
= nullptr;
1573 if (current_always
->type
!= AST_INITIAL
) {
1574 wire_en
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
1575 wire_en
->str
= id_en
;
1576 current_ast_mod
->children
.push_back(wire_en
);
1577 current_scope
[wire_en
->str
] = wire_en
;
1578 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
1581 std::vector
<RTLIL::State
> x_bits_addr
, x_bits_data
, set_bits_en
;
1582 for (int i
= 0; i
< addr_bits
; i
++)
1583 x_bits_addr
.push_back(RTLIL::State::Sx
);
1584 for (int i
= 0; i
< mem_width
; i
++)
1585 x_bits_data
.push_back(RTLIL::State::Sx
);
1586 for (int i
= 0; i
< mem_width
; i
++)
1587 set_bits_en
.push_back(RTLIL::State::S1
);
1589 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_addr
, false));
1590 assign_addr
->children
[0]->str
= id_addr
;
1592 AstNode
*assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_data
, false));
1593 assign_data
->children
[0]->str
= id_data
;
1595 AstNode
*assign_en
= nullptr;
1596 if (current_always
->type
!= AST_INITIAL
) {
1597 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, mem_width
));
1598 assign_en
->children
[0]->str
= id_en
;
1601 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
1602 default_signals
->children
.push_back(assign_addr
);
1603 default_signals
->children
.push_back(assign_data
);
1604 if (current_always
->type
!= AST_INITIAL
)
1605 default_signals
->children
.push_back(assign_en
);
1606 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
1608 assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
1609 assign_addr
->children
[0]->str
= id_addr
;
1611 if (children
[0]->children
.size() == 2)
1613 if (children
[0]->children
[1]->range_valid
)
1615 int offset
= children
[0]->children
[1]->range_right
;
1616 int width
= children
[0]->children
[1]->range_left
- offset
+ 1;
1617 offset
-= mem_data_range_offset
;
1619 std::vector
<RTLIL::State
> padding_x(offset
, RTLIL::State::Sx
);
1621 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1622 new AstNode(AST_CONCAT
, mkconst_bits(padding_x
, false), children
[1]->clone()));
1623 assign_data
->children
[0]->str
= id_data
;
1625 if (current_always
->type
!= AST_INITIAL
) {
1626 for (int i
= 0; i
< mem_width
; i
++)
1627 set_bits_en
[i
] = offset
<= i
&& i
< offset
+width
? RTLIL::State::S1
: RTLIL::State::S0
;
1628 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
1629 assign_en
->children
[0]->str
= id_en
;
1634 AstNode
*the_range
= children
[0]->children
[1];
1635 AstNode
*left_at_zero_ast
= the_range
->children
[0]->clone();
1636 AstNode
*right_at_zero_ast
= the_range
->children
.size() >= 2 ? the_range
->children
[1]->clone() : left_at_zero_ast
->clone();
1637 AstNode
*offset_ast
= right_at_zero_ast
->clone();
1639 if (mem_data_range_offset
)
1640 offset_ast
= new AstNode(AST_SUB
, offset_ast
, mkconst_int(mem_data_range_offset
, true));
1642 while (left_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
1643 while (right_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
1644 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
1645 log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n", str
.c_str(), filename
.c_str(), linenum
);
1646 int width
= left_at_zero_ast
->integer
- right_at_zero_ast
->integer
+ 1;
1648 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1649 new AstNode(AST_SHIFT_LEFT
, children
[1]->clone(), offset_ast
->clone()));
1650 assign_data
->children
[0]->str
= id_data
;
1652 if (current_always
->type
!= AST_INITIAL
) {
1653 for (int i
= 0; i
< mem_width
; i
++)
1654 set_bits_en
[i
] = i
< width
? RTLIL::State::S1
: RTLIL::State::S0
;
1655 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1656 new AstNode(AST_SHIFT_LEFT
, mkconst_bits(set_bits_en
, false), offset_ast
->clone()));
1657 assign_en
->children
[0]->str
= id_en
;
1660 delete left_at_zero_ast
;
1661 delete right_at_zero_ast
;
1667 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[1]->clone());
1668 assign_data
->children
[0]->str
= id_data
;
1670 if (current_always
->type
!= AST_INITIAL
) {
1671 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
1672 assign_en
->children
[0]->str
= id_en
;
1676 newNode
= new AstNode(AST_BLOCK
);
1677 newNode
->children
.push_back(assign_addr
);
1678 newNode
->children
.push_back(assign_data
);
1679 if (current_always
->type
!= AST_INITIAL
)
1680 newNode
->children
.push_back(assign_en
);
1682 AstNode
*wrnode
= new AstNode(current_always
->type
== AST_INITIAL
? AST_MEMINIT
: AST_MEMWR
);
1683 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1684 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1685 if (current_always
->type
!= AST_INITIAL
)
1686 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1688 wrnode
->children
.push_back(AstNode::mkconst_int(1, false));
1689 wrnode
->str
= children
[0]->str
;
1690 wrnode
->id2ast
= children
[0]->id2ast
;
1691 wrnode
->children
[0]->str
= id_addr
;
1692 wrnode
->children
[1]->str
= id_data
;
1693 if (current_always
->type
!= AST_INITIAL
)
1694 wrnode
->children
[2]->str
= id_en
;
1695 current_ast_mod
->children
.push_back(wrnode
);
1700 // replace function and task calls with the code from the function or task
1701 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && !str
.empty())
1703 if (type
== AST_FCALL
)
1705 if (str
== "\\$initstate")
1707 int myidx
= autoidx
++;
1709 AstNode
*wire
= new AstNode(AST_WIRE
);
1710 wire
->str
= stringf("$initstate$%d_wire", myidx
);
1711 current_ast_mod
->children
.push_back(wire
);
1712 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
1714 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
), new AstNode(AST_ARGUMENT
, new AstNode(AST_IDENTIFIER
)));
1715 cell
->str
= stringf("$initstate$%d", myidx
);
1716 cell
->children
[0]->str
= "$initstate";
1717 cell
->children
[1]->str
= "\\Y";
1718 cell
->children
[1]->children
[0]->str
= wire
->str
;
1719 cell
->children
[1]->children
[0]->id2ast
= wire
;
1720 current_ast_mod
->children
.push_back(cell
);
1721 while (cell
->simplify(true, false, false, 1, -1, false, false)) { }
1723 newNode
= new AstNode(AST_IDENTIFIER
);
1724 newNode
->str
= wire
->str
;
1725 newNode
->id2ast
= wire
;
1729 if (str
== "\\$past")
1731 if (width_hint
<= 0)
1732 goto replace_fcall_later
;
1736 if (GetSize(children
) != 1 && GetSize(children
) != 2)
1737 log_error("System function %s got %d arguments, expected 1 or 2 at %s:%d.\n",
1738 RTLIL::unescape_id(str
).c_str(), int(children
.size()), filename
.c_str(), linenum
);
1740 if (!current_always_clocked
)
1741 log_error("System function %s is only allowed in clocked blocks at %s:%d.\n",
1742 RTLIL::unescape_id(str
).c_str(), filename
.c_str(), linenum
);
1744 if (GetSize(children
) == 2)
1746 AstNode
*buf
= children
[1]->clone();
1747 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1748 if (buf
->type
!= AST_CONSTANT
)
1749 log_error("Failed to evaluate system function `%s' with non-constant value at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
1751 num_steps
= buf
->asInt(true);
1755 AstNode
*block
= nullptr;
1757 for (auto child
: current_always
->children
)
1758 if (child
->type
== AST_BLOCK
)
1761 log_assert(block
!= nullptr);
1763 int myidx
= autoidx
++;
1764 AstNode
*outreg
= nullptr;
1766 for (int i
= 0; i
< num_steps
; i
++)
1768 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
1769 mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
1771 reg
->str
= stringf("$past$%s:%d$%d$%d", filename
.c_str(), linenum
, myidx
, i
);
1774 current_ast_mod
->children
.push_back(reg
);
1776 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
1778 AstNode
*regid
= new AstNode(AST_IDENTIFIER
);
1779 regid
->str
= reg
->str
;
1780 regid
->id2ast
= reg
;
1782 AstNode
*rhs
= nullptr;
1784 if (outreg
== nullptr) {
1785 rhs
= children
.at(0)->clone();
1787 rhs
= new AstNode(AST_IDENTIFIER
);
1788 rhs
->str
= outreg
->str
;
1789 rhs
->id2ast
= outreg
;
1792 block
->children
.push_back(new AstNode(AST_ASSIGN_LE
, regid
, rhs
));
1796 newNode
= new AstNode(AST_IDENTIFIER
);
1797 newNode
->str
= outreg
->str
;
1798 newNode
->id2ast
= outreg
;
1802 if (str
== "\\$stable" || str
== "\\$rose" || str
== "\\$fell")
1804 if (GetSize(children
) != 1)
1805 log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
1806 RTLIL::unescape_id(str
).c_str(), int(children
.size()), filename
.c_str(), linenum
);
1808 if (!current_always_clocked
)
1809 log_error("System function %s is only allowed in clocked blocks at %s:%d.\n",
1810 RTLIL::unescape_id(str
).c_str(), filename
.c_str(), linenum
);
1812 AstNode
*present
= children
.at(0)->clone();
1813 AstNode
*past
= clone();
1814 past
->str
= "\\$past";
1816 if (str
== "\\$stable")
1817 newNode
= new AstNode(AST_EQ
, past
, present
);
1819 else if (str
== "\\$rose")
1820 newNode
= new AstNode(AST_LOGIC_AND
, new AstNode(AST_LOGIC_NOT
, past
), present
);
1822 else if (str
== "\\$fell")
1823 newNode
= new AstNode(AST_LOGIC_AND
, past
, new AstNode(AST_LOGIC_NOT
, present
));
1831 if (str
== "\\$rose" || str
== "\\$fell")
1833 if (GetSize(children
) != 1)
1834 log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
1835 RTLIL::unescape_id(str
).c_str(), int(children
.size()), filename
.c_str(), linenum
);
1837 if (!current_always_clocked
)
1838 log_error("System function %s is only allowed in clocked blocks at %s:%d.\n",
1839 RTLIL::unescape_id(str
).c_str(), filename
.c_str(), linenum
);
1841 newNode
= new AstNode(AST_EQ
, children
.at(0)->clone(), clone());
1842 newNode
->children
.at(1)->str
= "\\$past";
1846 // $anyconst and $anyseq are mapped in AstNode::genRTLIL()
1847 if (str
== "\\$anyconst" || str
== "\\$anyseq") {
1848 recursion_counter
--;
1852 if (str
== "\\$clog2")
1854 if (children
.size() != 1)
1855 log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
1856 RTLIL::unescape_id(str
).c_str(), int(children
.size()), filename
.c_str(), linenum
);
1858 AstNode
*buf
= children
[0]->clone();
1859 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1860 if (buf
->type
!= AST_CONSTANT
)
1861 log_error("Failed to evaluate system function `%s' with non-constant value at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
1863 RTLIL::Const arg_value
= buf
->bitsAsConst();
1864 if (arg_value
.as_bool())
1865 arg_value
= const_sub(arg_value
, 1, false, false, GetSize(arg_value
));
1868 uint32_t result
= 0;
1869 for (size_t i
= 0; i
< arg_value
.bits
.size(); i
++)
1870 if (arg_value
.bits
.at(i
) == RTLIL::State::S1
)
1873 newNode
= mkconst_int(result
, false);
1877 if (str
== "\\$size" || str
== "\\$bits")
1879 if (str
== "\\$bits" && children
.size() != 1)
1880 log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
1881 RTLIL::unescape_id(str
).c_str(), int(children
.size()), filename
.c_str(), linenum
);
1883 if (str
== "\\$size" && children
.size() != 1 && children
.size() != 2)
1884 log_error("System function %s got %d arguments, expected 1 or 2 at %s:%d.\n",
1885 RTLIL::unescape_id(str
).c_str(), int(children
.size()), filename
.c_str(), linenum
);
1888 if (str
== "\\$size" && children
.size() == 2) {
1889 AstNode
*buf
= children
[1]->clone();
1890 // Evaluate constant expression
1891 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1892 dim
= buf
->asInt(false);
1895 AstNode
*buf
= children
[0]->clone();
1897 AstNode
*id_ast
= NULL
;
1900 //while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1901 buf
->detectSignWidth(width_hint
, sign_hint
);
1903 if (buf
->type
== AST_IDENTIFIER
) {
1904 id_ast
= buf
->id2ast
;
1905 if (id_ast
== NULL
&& current_scope
.count(buf
->str
))
1906 id_ast
= current_scope
.at(buf
->str
);
1908 log_error("Failed to resolve identifier %s for width detection at %s:%d!\n", buf
->str
.c_str(), filename
.c_str(), linenum
);
1909 if (id_ast
->type
== AST_MEMORY
) {
1910 // We got here only if the argument is a memory
1911 // Otherwise $size() and $bits() return the expression width
1912 AstNode
*mem_range
= id_ast
->children
[1];
1913 if (str
== "\\$bits") {
1914 if (mem_range
->type
== AST_RANGE
) {
1915 if (!mem_range
->range_valid
)
1916 log_error("Failed to detect width of memory access `%s' at %s:%d!\n", buf
->str
.c_str(), filename
.c_str(), linenum
);
1917 mem_depth
= mem_range
->range_left
- mem_range
->range_right
+ 1;
1919 log_error("Unknown memory depth AST type in `%s' at %s:%d!\n", buf
->str
.c_str(), filename
.c_str(), linenum
);
1922 if (mem_range
->type
== AST_RANGE
) {
1923 if (!mem_range
->range_valid
)
1924 log_error("Failed to detect width of memory access `%s' at %s:%d!\n", buf
->str
.c_str(), filename
.c_str(), linenum
);
1926 if (id_ast
->multirange_dimensions
.empty())
1929 dims
= GetSize(id_ast
->multirange_dimensions
)/2;
1931 width_hint
= (dims
> 1) ? id_ast
->multirange_dimensions
[1] : (mem_range
->range_left
- mem_range
->range_right
+ 1);
1932 else if (dim
<= dims
) {
1933 width_hint
= id_ast
->multirange_dimensions
[2*dim
-1];
1934 } else if ((dim
> dims
+1) || (dim
< 0))
1935 log_error("Dimension %d out of range in `%s', as it only has dimensions 1..%d at %s:%d!\n", dim
, buf
->str
.c_str(), dims
+1, filename
.c_str(), linenum
);
1937 log_error("Unknown memory depth AST type in `%s' at %s:%d!\n", buf
->str
.c_str(), filename
.c_str(), linenum
);
1943 newNode
= mkconst_int(width_hint
* mem_depth
, false);
1947 if (str
== "\\$ln" || str
== "\\$log10" || str
== "\\$exp" || str
== "\\$sqrt" || str
== "\\$pow" ||
1948 str
== "\\$floor" || str
== "\\$ceil" || str
== "\\$sin" || str
== "\\$cos" || str
== "\\$tan" ||
1949 str
== "\\$asin" || str
== "\\$acos" || str
== "\\$atan" || str
== "\\$atan2" || str
== "\\$hypot" ||
1950 str
== "\\$sinh" || str
== "\\$cosh" || str
== "\\$tanh" || str
== "\\$asinh" || str
== "\\$acosh" || str
== "\\$atanh" ||
1951 str
== "\\$rtoi" || str
== "\\$itor")
1953 bool func_with_two_arguments
= str
== "\\$pow" || str
== "\\$atan2" || str
== "\\$hypot";
1954 double x
= 0, y
= 0;
1956 if (func_with_two_arguments
) {
1957 if (children
.size() != 2)
1958 log_error("System function %s got %d arguments, expected 2 at %s:%d.\n",
1959 RTLIL::unescape_id(str
).c_str(), int(children
.size()), filename
.c_str(), linenum
);
1961 if (children
.size() != 1)
1962 log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
1963 RTLIL::unescape_id(str
).c_str(), int(children
.size()), filename
.c_str(), linenum
);
1966 if (children
.size() >= 1) {
1967 while (children
[0]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1968 if (!children
[0]->isConst())
1969 log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
1970 RTLIL::unescape_id(str
).c_str(), filename
.c_str(), linenum
);
1971 int child_width_hint
= width_hint
;
1972 bool child_sign_hint
= sign_hint
;
1973 children
[0]->detectSignWidth(child_width_hint
, child_sign_hint
);
1974 x
= children
[0]->asReal(child_sign_hint
);
1977 if (children
.size() >= 2) {
1978 while (children
[1]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1979 if (!children
[1]->isConst())
1980 log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
1981 RTLIL::unescape_id(str
).c_str(), filename
.c_str(), linenum
);
1982 int child_width_hint
= width_hint
;
1983 bool child_sign_hint
= sign_hint
;
1984 children
[1]->detectSignWidth(child_width_hint
, child_sign_hint
);
1985 y
= children
[1]->asReal(child_sign_hint
);
1988 if (str
== "\\$rtoi") {
1989 newNode
= AstNode::mkconst_int(x
, true);
1991 newNode
= new AstNode(AST_REALVALUE
);
1992 if (str
== "\\$ln") newNode
->realvalue
= ::log(x
);
1993 else if (str
== "\\$log10") newNode
->realvalue
= ::log10(x
);
1994 else if (str
== "\\$exp") newNode
->realvalue
= ::exp(x
);
1995 else if (str
== "\\$sqrt") newNode
->realvalue
= ::sqrt(x
);
1996 else if (str
== "\\$pow") newNode
->realvalue
= ::pow(x
, y
);
1997 else if (str
== "\\$floor") newNode
->realvalue
= ::floor(x
);
1998 else if (str
== "\\$ceil") newNode
->realvalue
= ::ceil(x
);
1999 else if (str
== "\\$sin") newNode
->realvalue
= ::sin(x
);
2000 else if (str
== "\\$cos") newNode
->realvalue
= ::cos(x
);
2001 else if (str
== "\\$tan") newNode
->realvalue
= ::tan(x
);
2002 else if (str
== "\\$asin") newNode
->realvalue
= ::asin(x
);
2003 else if (str
== "\\$acos") newNode
->realvalue
= ::acos(x
);
2004 else if (str
== "\\$atan") newNode
->realvalue
= ::atan(x
);
2005 else if (str
== "\\$atan2") newNode
->realvalue
= ::atan2(x
, y
);
2006 else if (str
== "\\$hypot") newNode
->realvalue
= ::hypot(x
, y
);
2007 else if (str
== "\\$sinh") newNode
->realvalue
= ::sinh(x
);
2008 else if (str
== "\\$cosh") newNode
->realvalue
= ::cosh(x
);
2009 else if (str
== "\\$tanh") newNode
->realvalue
= ::tanh(x
);
2010 else if (str
== "\\$asinh") newNode
->realvalue
= ::asinh(x
);
2011 else if (str
== "\\$acosh") newNode
->realvalue
= ::acosh(x
);
2012 else if (str
== "\\$atanh") newNode
->realvalue
= ::atanh(x
);
2013 else if (str
== "\\$itor") newNode
->realvalue
= x
;
2019 if (current_scope
.count(str
) != 0 && current_scope
[str
]->type
== AST_DPI_FUNCTION
)
2021 AstNode
*dpi_decl
= current_scope
[str
];
2023 std::string rtype
, fname
;
2024 std::vector
<std::string
> argtypes
;
2025 std::vector
<AstNode
*> args
;
2027 rtype
= RTLIL::unescape_id(dpi_decl
->children
.at(0)->str
);
2028 fname
= RTLIL::unescape_id(dpi_decl
->children
.at(1)->str
);
2030 for (int i
= 2; i
< GetSize(dpi_decl
->children
); i
++)
2032 if (i
-2 >= GetSize(children
))
2033 log_error("Insufficient number of arguments in DPI function call at %s:%d.\n", filename
.c_str(), linenum
);
2035 argtypes
.push_back(RTLIL::unescape_id(dpi_decl
->children
.at(i
)->str
));
2036 args
.push_back(children
.at(i
-2)->clone());
2037 while (args
.back()->simplify(true, false, false, stage
, -1, false, true)) { }
2039 if (args
.back()->type
!= AST_CONSTANT
&& args
.back()->type
!= AST_REALVALUE
)
2040 log_error("Failed to evaluate DPI function with non-constant argument at %s:%d.\n", filename
.c_str(), linenum
);
2043 newNode
= dpi_call(rtype
, fname
, argtypes
, args
);
2045 for (auto arg
: args
)
2051 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_FUNCTION
)
2052 log_error("Can't resolve function name `%s' at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
2055 if (type
== AST_TCALL
)
2057 if (str
== "$finish" || str
== "$stop")
2059 if (!current_always
|| current_always
->type
!= AST_INITIAL
)
2060 log_error("System task `%s' outside initial block is unsupported at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
2062 log_error("System task `%s' executed at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
2065 if (str
== "\\$readmemh" || str
== "\\$readmemb")
2067 if (GetSize(children
) < 2 || GetSize(children
) > 4)
2068 log_error("System function %s got %d arguments, expected 2-4 at %s:%d.\n",
2069 RTLIL::unescape_id(str
).c_str(), int(children
.size()), filename
.c_str(), linenum
);
2071 AstNode
*node_filename
= children
[0]->clone();
2072 while (node_filename
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2073 if (node_filename
->type
!= AST_CONSTANT
)
2074 log_error("Failed to evaluate system function `%s' with non-constant 1st argument at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
2076 AstNode
*node_memory
= children
[1]->clone();
2077 while (node_memory
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2078 if (node_memory
->type
!= AST_IDENTIFIER
|| node_memory
->id2ast
== nullptr || node_memory
->id2ast
->type
!= AST_MEMORY
)
2079 log_error("Failed to evaluate system function `%s' with non-memory 2nd argument at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
2081 int start_addr
= -1, finish_addr
= -1;
2083 if (GetSize(children
) > 2) {
2084 AstNode
*node_addr
= children
[2]->clone();
2085 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2086 if (node_addr
->type
!= AST_CONSTANT
)
2087 log_error("Failed to evaluate system function `%s' with non-constant 3rd argument at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
2088 start_addr
= int(node_addr
->asInt(false));
2091 if (GetSize(children
) > 3) {
2092 AstNode
*node_addr
= children
[3]->clone();
2093 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2094 if (node_addr
->type
!= AST_CONSTANT
)
2095 log_error("Failed to evaluate system function `%s' with non-constant 4th argument at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
2096 finish_addr
= int(node_addr
->asInt(false));
2099 bool unconditional_init
= false;
2100 if (current_always
->type
== AST_INITIAL
) {
2101 pool
<AstNode
*> queue
;
2102 log_assert(current_always
->children
[0]->type
== AST_BLOCK
);
2103 queue
.insert(current_always
->children
[0]);
2104 while (!unconditional_init
&& !queue
.empty()) {
2105 pool
<AstNode
*> next_queue
;
2106 for (auto n
: queue
)
2107 for (auto c
: n
->children
) {
2109 unconditional_init
= true;
2110 next_queue
.insert(c
);
2112 next_queue
.swap(queue
);
2116 newNode
= readmem(str
== "\\$readmemh", node_filename
->bitsAsConst().decode_string(), node_memory
->id2ast
, start_addr
, finish_addr
, unconditional_init
);
2120 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_TASK
)
2121 log_error("Can't resolve task name `%s' at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
2124 AstNode
*decl
= current_scope
[str
];
2126 std::stringstream sstr
;
2127 sstr
<< "$func$" << str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++) << "$";
2128 std::string prefix
= sstr
.str();
2130 bool recommend_const_eval
= false;
2131 bool require_const_eval
= in_param
? false : has_const_only_constructs(recommend_const_eval
);
2132 if ((in_param
|| recommend_const_eval
|| require_const_eval
) && !decl
->attributes
.count("\\via_celltype"))
2134 bool all_args_const
= true;
2135 for (auto child
: children
) {
2136 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
2137 if (child
->type
!= AST_CONSTANT
)
2138 all_args_const
= false;
2141 if (all_args_const
) {
2142 AstNode
*func_workspace
= current_scope
[str
]->clone();
2143 newNode
= func_workspace
->eval_const_function(this);
2144 delete func_workspace
;
2149 log_error("Non-constant function call in constant expression at %s:%d.\n", filename
.c_str(), linenum
);
2150 if (require_const_eval
)
2151 log_error("Function %s can only be called with constant arguments at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
2154 size_t arg_count
= 0;
2155 std::map
<std::string
, std::string
> replace_rules
;
2156 vector
<AstNode
*> added_mod_children
;
2157 dict
<std::string
, AstNode
*> wire_cache
;
2159 if (current_block
== NULL
)
2161 log_assert(type
== AST_FCALL
);
2163 AstNode
*wire
= NULL
;
2164 for (auto child
: decl
->children
)
2165 if (child
->type
== AST_WIRE
&& child
->str
== str
)
2166 wire
= child
->clone();
2167 log_assert(wire
!= NULL
);
2169 wire
->str
= prefix
+ str
;
2171 wire
->is_input
= false;
2172 wire
->is_output
= false;
2174 current_ast_mod
->children
.push_back(wire
);
2175 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2177 AstNode
*lvalue
= new AstNode(AST_IDENTIFIER
);
2178 lvalue
->str
= wire
->str
;
2180 AstNode
*always
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
,
2181 new AstNode(AST_ASSIGN_EQ
, lvalue
, clone())));
2182 current_ast_mod
->children
.push_back(always
);
2184 goto replace_fcall_with_id
;
2187 if (decl
->attributes
.count("\\via_celltype"))
2189 std::string celltype
= decl
->attributes
.at("\\via_celltype")->asAttrConst().decode_string();
2190 std::string outport
= str
;
2192 if (celltype
.find(' ') != std::string::npos
) {
2193 int pos
= celltype
.find(' ');
2194 outport
= RTLIL::escape_id(celltype
.substr(pos
+1));
2195 celltype
= RTLIL::escape_id(celltype
.substr(0, pos
));
2197 celltype
= RTLIL::escape_id(celltype
);
2199 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
));
2200 cell
->str
= prefix
.substr(0, GetSize(prefix
)-1);
2201 cell
->children
[0]->str
= celltype
;
2203 for (auto attr
: decl
->attributes
)
2204 if (attr
.first
.str().rfind("\\via_celltype_defparam_", 0) == 0)
2206 AstNode
*cell_arg
= new AstNode(AST_PARASET
, attr
.second
->clone());
2207 cell_arg
->str
= RTLIL::escape_id(attr
.first
.str().substr(strlen("\\via_celltype_defparam_")));
2208 cell
->children
.push_back(cell_arg
);
2211 for (auto child
: decl
->children
)
2212 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
|| (type
== AST_FCALL
&& child
->str
== str
)))
2214 AstNode
*wire
= child
->clone();
2215 wire
->str
= prefix
+ wire
->str
;
2217 wire
->is_input
= false;
2218 wire
->is_output
= false;
2219 current_ast_mod
->children
.push_back(wire
);
2220 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2222 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
2223 wire_id
->str
= wire
->str
;
2225 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
2227 AstNode
*arg
= children
[arg_count
++]->clone();
2228 AstNode
*assign
= child
->is_input
?
2229 new AstNode(AST_ASSIGN_EQ
, wire_id
->clone(), arg
) :
2230 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
->clone());
2232 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
2233 if (*it
!= current_block_child
)
2235 current_block
->children
.insert(it
, assign
);
2240 AstNode
*cell_arg
= new AstNode(AST_ARGUMENT
, wire_id
);
2241 cell_arg
->str
= child
->str
== str
? outport
: child
->str
;
2242 cell
->children
.push_back(cell_arg
);
2245 current_ast_mod
->children
.push_back(cell
);
2246 goto replace_fcall_with_id
;
2249 for (auto child
: decl
->children
)
2250 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
)
2252 AstNode
*wire
= nullptr;
2254 if (wire_cache
.count(child
->str
))
2256 wire
= wire_cache
.at(child
->str
);
2257 if (wire
->children
.empty()) {
2258 for (auto c
: child
->children
)
2259 wire
->children
.push_back(c
->clone());
2260 } else if (!child
->children
.empty()) {
2261 while (child
->simplify(true, false, false, stage
, -1, false, false)) { }
2262 if (GetSize(child
->children
) == GetSize(wire
->children
)) {
2263 for (int i
= 0; i
< GetSize(child
->children
); i
++)
2264 if (*child
->children
.at(i
) != *wire
->children
.at(i
))
2265 goto tcall_incompatible_wires
;
2267 tcall_incompatible_wires
:
2268 log_error("Incompatible re-declaration of wire %s at %s:%d.\n", child
->str
.c_str(), filename
.c_str(), linenum
);
2274 wire
= child
->clone();
2275 wire
->str
= prefix
+ wire
->str
;
2277 wire
->is_input
= false;
2278 wire
->is_output
= false;
2279 if (!child
->is_output
)
2280 wire
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
2281 wire_cache
[child
->str
] = wire
;
2283 current_ast_mod
->children
.push_back(wire
);
2284 added_mod_children
.push_back(wire
);
2287 if (child
->type
== AST_WIRE
)
2288 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2290 replace_rules
[child
->str
] = wire
->str
;
2291 current_scope
[wire
->str
] = wire
;
2293 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
2295 AstNode
*arg
= children
[arg_count
++]->clone();
2296 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
2297 wire_id
->str
= wire
->str
;
2298 AstNode
*assign
= child
->is_input
?
2299 new AstNode(AST_ASSIGN_EQ
, wire_id
, arg
) :
2300 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
);
2302 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
2303 if (*it
!= current_block_child
)
2305 current_block
->children
.insert(it
, assign
);
2311 for (auto child
: added_mod_children
) {
2312 child
->replace_ids(prefix
, replace_rules
);
2313 while (child
->simplify(true, false, false, 1, -1, false, false)) { }
2316 for (auto child
: decl
->children
)
2317 if (child
->type
!= AST_WIRE
&& child
->type
!= AST_MEMORY
&& child
->type
!= AST_PARAMETER
&& child
->type
!= AST_LOCALPARAM
)
2319 AstNode
*stmt
= child
->clone();
2320 stmt
->replace_ids(prefix
, replace_rules
);
2322 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
2323 if (*it
!= current_block_child
)
2325 current_block
->children
.insert(it
, stmt
);
2330 replace_fcall_with_id
:
2331 if (type
== AST_FCALL
) {
2333 type
= AST_IDENTIFIER
;
2336 if (type
== AST_TCALL
)
2338 did_something
= true;
2341 replace_fcall_later
:;
2343 // perform const folding when activated
2347 std::vector
<RTLIL::State
> tmp_bits
;
2348 RTLIL::Const (*const_func
)(const RTLIL::Const
&, const RTLIL::Const
&, bool, bool, int);
2349 RTLIL::Const dummy_arg
;
2353 case AST_IDENTIFIER
:
2354 if (current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
)) {
2355 if (current_scope
[str
]->children
[0]->type
== AST_CONSTANT
) {
2356 if (children
.size() != 0 && children
[0]->type
== AST_RANGE
&& children
[0]->range_valid
) {
2357 std::vector
<RTLIL::State
> data
;
2358 bool param_upto
= current_scope
[str
]->range_valid
&& current_scope
[str
]->range_swapped
;
2359 int param_offset
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_right
: 0;
2360 int param_width
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_left
- current_scope
[str
]->range_right
+ 1 :
2361 GetSize(current_scope
[str
]->children
[0]->bits
);
2362 int tmp_range_left
= children
[0]->range_left
, tmp_range_right
= children
[0]->range_right
;
2364 tmp_range_left
= (param_width
+ 2*param_offset
) - children
[0]->range_right
- 1;
2365 tmp_range_right
= (param_width
+ 2*param_offset
) - children
[0]->range_left
- 1;
2367 for (int i
= tmp_range_right
; i
<= tmp_range_left
; i
++) {
2368 int index
= i
- param_offset
;
2369 if (0 <= index
&& index
< param_width
)
2370 data
.push_back(current_scope
[str
]->children
[0]->bits
[index
]);
2372 data
.push_back(RTLIL::State::Sx
);
2374 newNode
= mkconst_bits(data
, false);
2376 if (children
.size() == 0)
2377 newNode
= current_scope
[str
]->children
[0]->clone();
2379 if (current_scope
[str
]->children
[0]->isConst())
2380 newNode
= current_scope
[str
]->children
[0]->clone();
2382 else if (at_zero
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_WIRE
|| current_scope
[str
]->type
== AST_AUTOWIRE
)) {
2383 newNode
= mkconst_int(0, sign_hint
, width_hint
);
2387 if (children
[0]->type
== AST_CONSTANT
) {
2388 RTLIL::Const y
= RTLIL::const_not(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
2389 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2393 case AST_TO_UNSIGNED
:
2394 if (children
[0]->type
== AST_CONSTANT
) {
2395 RTLIL::Const y
= children
[0]->bitsAsConst(width_hint
, sign_hint
);
2396 newNode
= mkconst_bits(y
.bits
, type
== AST_TO_SIGNED
);
2399 if (0) { case AST_BIT_AND
: const_func
= RTLIL::const_and
; }
2400 if (0) { case AST_BIT_OR
: const_func
= RTLIL::const_or
; }
2401 if (0) { case AST_BIT_XOR
: const_func
= RTLIL::const_xor
; }
2402 if (0) { case AST_BIT_XNOR
: const_func
= RTLIL::const_xnor
; }
2403 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2404 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
2405 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
2406 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2409 if (0) { case AST_REDUCE_AND
: const_func
= RTLIL::const_reduce_and
; }
2410 if (0) { case AST_REDUCE_OR
: const_func
= RTLIL::const_reduce_or
; }
2411 if (0) { case AST_REDUCE_XOR
: const_func
= RTLIL::const_reduce_xor
; }
2412 if (0) { case AST_REDUCE_XNOR
: const_func
= RTLIL::const_reduce_xnor
; }
2413 if (0) { case AST_REDUCE_BOOL
: const_func
= RTLIL::const_reduce_bool
; }
2414 if (children
[0]->type
== AST_CONSTANT
) {
2415 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), dummy_arg
, false, false, -1);
2416 newNode
= mkconst_bits(y
.bits
, false);
2420 if (children
[0]->type
== AST_CONSTANT
) {
2421 RTLIL::Const y
= RTLIL::const_logic_not(RTLIL::Const(children
[0]->bits
), dummy_arg
, children
[0]->is_signed
, false, -1);
2422 newNode
= mkconst_bits(y
.bits
, false);
2424 if (children
[0]->isConst()) {
2425 newNode
= mkconst_int(children
[0]->asReal(sign_hint
) == 0, false, 1);
2428 if (0) { case AST_LOGIC_AND
: const_func
= RTLIL::const_logic_and
; }
2429 if (0) { case AST_LOGIC_OR
: const_func
= RTLIL::const_logic_or
; }
2430 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2431 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), RTLIL::Const(children
[1]->bits
),
2432 children
[0]->is_signed
, children
[1]->is_signed
, -1);
2433 newNode
= mkconst_bits(y
.bits
, false);
2435 if (children
[0]->isConst() && children
[1]->isConst()) {
2436 if (type
== AST_LOGIC_AND
)
2437 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) && (children
[1]->asReal(sign_hint
) != 0), false, 1);
2439 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) || (children
[1]->asReal(sign_hint
) != 0), false, 1);
2442 if (0) { case AST_SHIFT_LEFT
: const_func
= RTLIL::const_shl
; }
2443 if (0) { case AST_SHIFT_RIGHT
: const_func
= RTLIL::const_shr
; }
2444 if (0) { case AST_SHIFT_SLEFT
: const_func
= RTLIL::const_sshl
; }
2445 if (0) { case AST_SHIFT_SRIGHT
: const_func
= RTLIL::const_sshr
; }
2446 if (0) { case AST_POW
: const_func
= RTLIL::const_pow
; }
2447 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2448 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
2449 RTLIL::Const(children
[1]->bits
), sign_hint
, type
== AST_POW
? children
[1]->is_signed
: false, width_hint
);
2450 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2452 if (type
== AST_POW
&& children
[0]->isConst() && children
[1]->isConst()) {
2453 newNode
= new AstNode(AST_REALVALUE
);
2454 newNode
->realvalue
= pow(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
));
2457 if (0) { case AST_LT
: const_func
= RTLIL::const_lt
; }
2458 if (0) { case AST_LE
: const_func
= RTLIL::const_le
; }
2459 if (0) { case AST_EQ
: const_func
= RTLIL::const_eq
; }
2460 if (0) { case AST_NE
: const_func
= RTLIL::const_ne
; }
2461 if (0) { case AST_EQX
: const_func
= RTLIL::const_eqx
; }
2462 if (0) { case AST_NEX
: const_func
= RTLIL::const_nex
; }
2463 if (0) { case AST_GE
: const_func
= RTLIL::const_ge
; }
2464 if (0) { case AST_GT
: const_func
= RTLIL::const_gt
; }
2465 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2466 int cmp_width
= max(children
[0]->bits
.size(), children
[1]->bits
.size());
2467 bool cmp_signed
= children
[0]->is_signed
&& children
[1]->is_signed
;
2468 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(cmp_width
, cmp_signed
),
2469 children
[1]->bitsAsConst(cmp_width
, cmp_signed
), cmp_signed
, cmp_signed
, 1);
2470 newNode
= mkconst_bits(y
.bits
, false);
2472 if (children
[0]->isConst() && children
[1]->isConst()) {
2473 bool cmp_signed
= (children
[0]->type
== AST_REALVALUE
|| children
[0]->is_signed
) && (children
[1]->type
== AST_REALVALUE
|| children
[1]->is_signed
);
2475 case AST_LT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) < children
[1]->asReal(cmp_signed
), false, 1); break;
2476 case AST_LE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) <= children
[1]->asReal(cmp_signed
), false, 1); break;
2477 case AST_EQ
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
2478 case AST_NE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
2479 case AST_EQX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
2480 case AST_NEX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
2481 case AST_GE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) >= children
[1]->asReal(cmp_signed
), false, 1); break;
2482 case AST_GT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) > children
[1]->asReal(cmp_signed
), false, 1); break;
2483 default: log_abort();
2487 if (0) { case AST_ADD
: const_func
= RTLIL::const_add
; }
2488 if (0) { case AST_SUB
: const_func
= RTLIL::const_sub
; }
2489 if (0) { case AST_MUL
: const_func
= RTLIL::const_mul
; }
2490 if (0) { case AST_DIV
: const_func
= RTLIL::const_div
; }
2491 if (0) { case AST_MOD
: const_func
= RTLIL::const_mod
; }
2492 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2493 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
2494 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
2495 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2497 if (children
[0]->isConst() && children
[1]->isConst()) {
2498 newNode
= new AstNode(AST_REALVALUE
);
2500 case AST_ADD
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) + children
[1]->asReal(sign_hint
); break;
2501 case AST_SUB
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) - children
[1]->asReal(sign_hint
); break;
2502 case AST_MUL
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) * children
[1]->asReal(sign_hint
); break;
2503 case AST_DIV
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) / children
[1]->asReal(sign_hint
); break;
2504 case AST_MOD
: newNode
->realvalue
= fmod(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
)); break;
2505 default: log_abort();
2509 if (0) { case AST_POS
: const_func
= RTLIL::const_pos
; }
2510 if (0) { case AST_NEG
: const_func
= RTLIL::const_neg
; }
2511 if (children
[0]->type
== AST_CONSTANT
) {
2512 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
2513 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2515 if (children
[0]->isConst()) {
2516 newNode
= new AstNode(AST_REALVALUE
);
2517 if (type
== AST_POS
)
2518 newNode
->realvalue
= +children
[0]->asReal(sign_hint
);
2520 newNode
->realvalue
= -children
[0]->asReal(sign_hint
);
2524 if (children
[0]->isConst())
2526 bool found_sure_true
= false;
2527 bool found_maybe_true
= false;
2529 if (children
[0]->type
== AST_CONSTANT
)
2530 for (auto &bit
: children
[0]->bits
) {
2531 if (bit
== RTLIL::State::S1
)
2532 found_sure_true
= true;
2533 if (bit
> RTLIL::State::S1
)
2534 found_maybe_true
= true;
2537 found_sure_true
= children
[0]->asReal(sign_hint
) != 0;
2539 AstNode
*choice
= NULL
, *not_choice
= NULL
;
2540 if (found_sure_true
)
2541 choice
= children
[1], not_choice
= children
[2];
2542 else if (!found_maybe_true
)
2543 choice
= children
[2], not_choice
= children
[1];
2545 if (choice
!= NULL
) {
2546 if (choice
->type
== AST_CONSTANT
) {
2547 int other_width_hint
= width_hint
;
2548 bool other_sign_hint
= sign_hint
, other_real
= false;
2549 not_choice
->detectSignWidth(other_width_hint
, other_sign_hint
, &other_real
);
2551 newNode
= new AstNode(AST_REALVALUE
);
2552 choice
->detectSignWidth(width_hint
, sign_hint
);
2553 newNode
->realvalue
= choice
->asReal(sign_hint
);
2555 RTLIL::Const y
= choice
->bitsAsConst(width_hint
, sign_hint
);
2556 if (choice
->is_string
&& y
.bits
.size() % 8 == 0 && sign_hint
== false)
2557 newNode
= mkconst_str(y
.bits
);
2559 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2562 if (choice
->isConst()) {
2563 newNode
= choice
->clone();
2565 } else if (children
[1]->type
== AST_CONSTANT
&& children
[2]->type
== AST_CONSTANT
) {
2566 RTLIL::Const a
= children
[1]->bitsAsConst(width_hint
, sign_hint
);
2567 RTLIL::Const b
= children
[2]->bitsAsConst(width_hint
, sign_hint
);
2568 log_assert(a
.bits
.size() == b
.bits
.size());
2569 for (size_t i
= 0; i
< a
.bits
.size(); i
++)
2570 if (a
.bits
[i
] != b
.bits
[i
])
2571 a
.bits
[i
] = RTLIL::State::Sx
;
2572 newNode
= mkconst_bits(a
.bits
, sign_hint
);
2573 } else if (children
[1]->isConst() && children
[2]->isConst()) {
2574 newNode
= new AstNode(AST_REALVALUE
);
2575 if (children
[1]->asReal(sign_hint
) == children
[2]->asReal(sign_hint
))
2576 newNode
->realvalue
= children
[1]->asReal(sign_hint
);
2578 // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
2579 // the data type in question should be returned if the ?: is ambiguous. The
2580 // value in Table 7-1 for the 'real' type is 0.0.
2581 newNode
->realvalue
= 0.0;
2586 string_op
= !children
.empty();
2587 for (auto it
= children
.begin(); it
!= children
.end(); it
++) {
2588 if ((*it
)->type
!= AST_CONSTANT
)
2590 if (!(*it
)->is_string
)
2592 tmp_bits
.insert(tmp_bits
.end(), (*it
)->bits
.begin(), (*it
)->bits
.end());
2594 newNode
= string_op
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
2597 if (children
.at(0)->type
!= AST_CONSTANT
|| children
.at(1)->type
!= AST_CONSTANT
)
2599 for (int i
= 0; i
< children
[0]->bitsAsConst().as_int(); i
++)
2600 tmp_bits
.insert(tmp_bits
.end(), children
.at(1)->bits
.begin(), children
.at(1)->bits
.end());
2601 newNode
= children
.at(1)->is_string
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
2609 // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
2612 // fprintf(stderr, "----\n");
2613 // dumpAst(stderr, "- ");
2614 // newNode->dumpAst(stderr, "+ ");
2615 log_assert(newNode
!= NULL
);
2616 newNode
->filename
= filename
;
2617 newNode
->linenum
= linenum
;
2618 newNode
->cloneInto(this);
2620 did_something
= true;
2626 recursion_counter
--;
2627 return did_something
;
2630 static void replace_result_wire_name_in_function(AstNode
*node
, std::string
&from
, std::string
&to
)
2632 for (auto &it
: node
->children
)
2633 replace_result_wire_name_in_function(it
, from
, to
);
2634 if (node
->str
== from
)
2638 // replace a readmem[bh] TCALL ast node with a block of memory assignments
2639 AstNode
*AstNode::readmem(bool is_readmemh
, std::string mem_filename
, AstNode
*memory
, int start_addr
, int finish_addr
, bool unconditional_init
)
2641 int mem_width
, mem_size
, addr_bits
;
2642 memory
->meminfo(mem_width
, mem_size
, addr_bits
);
2644 AstNode
*block
= new AstNode(AST_BLOCK
);
2646 AstNode
*meminit
= nullptr;
2647 int next_meminit_cursor
=0;
2648 vector
<State
> meminit_bits
;
2652 f
.open(mem_filename
.c_str());
2655 log_error("Can not open file `%s` for %s at %s:%d.\n", mem_filename
.c_str(), str
.c_str(), filename
.c_str(), linenum
);
2657 log_assert(GetSize(memory
->children
) == 2 && memory
->children
[1]->type
== AST_RANGE
&& memory
->children
[1]->range_valid
);
2658 int range_left
= memory
->children
[1]->range_left
, range_right
= memory
->children
[1]->range_right
;
2659 int range_min
= min(range_left
, range_right
), range_max
= max(range_left
, range_right
);
2662 start_addr
= range_min
;
2664 if (finish_addr
< 0)
2665 finish_addr
= range_max
+ 1;
2667 bool in_comment
= false;
2668 int increment
= start_addr
<= finish_addr
? +1 : -1;
2669 int cursor
= start_addr
;
2673 std::string line
, token
;
2674 std::getline(f
, line
);
2676 for (int i
= 0; i
< GetSize(line
); i
++) {
2677 if (in_comment
&& line
.substr(i
, 2) == "*/") {
2683 if (!in_comment
&& line
.substr(i
, 2) == "/*")
2691 token
= next_token(line
, " \t\r\n");
2692 if (token
.empty() || token
.substr(0, 2) == "//")
2695 if (token
[0] == '@') {
2696 token
= token
.substr(1);
2697 const char *nptr
= token
.c_str();
2699 cursor
= strtol(nptr
, &endptr
, 16);
2700 if (!*nptr
|| *endptr
)
2701 log_error("Can not parse address `%s` for %s at %s:%d.\n", nptr
, str
.c_str(), filename
.c_str(), linenum
);
2705 AstNode
*value
= VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width
, is_readmemh
? 'h' : 'b') + token
);
2707 if (unconditional_init
)
2709 if (meminit
== nullptr || cursor
!= next_meminit_cursor
)
2711 if (meminit
!= nullptr) {
2712 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
2713 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
2716 meminit
= new AstNode(AST_MEMINIT
);
2717 meminit
->children
.push_back(AstNode::mkconst_int(cursor
, false));
2718 meminit
->children
.push_back(nullptr);
2719 meminit
->children
.push_back(nullptr);
2720 meminit
->str
= memory
->str
;
2721 meminit
->id2ast
= memory
;
2722 meminit_bits
.clear();
2725 current_ast_mod
->children
.push_back(meminit
);
2726 next_meminit_cursor
= cursor
;
2730 next_meminit_cursor
++;
2731 meminit_bits
.insert(meminit_bits
.end(), value
->bits
.begin(), value
->bits
.end());
2736 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
, false))), value
));
2737 block
->children
.back()->children
[0]->str
= memory
->str
;
2738 block
->children
.back()->children
[0]->id2ast
= memory
;
2741 cursor
+= increment
;
2742 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
2746 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
2750 if (meminit
!= nullptr) {
2751 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
2752 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
2758 // annotate the names of all wires and other named objects in a generate block
2759 void AstNode::expand_genblock(std::string index_var
, std::string prefix
, std::map
<std::string
, std::string
> &name_map
)
2761 if (!index_var
.empty() && type
== AST_IDENTIFIER
&& str
== index_var
) {
2762 current_scope
[index_var
]->children
[0]->cloneInto(this);
2766 if ((type
== AST_IDENTIFIER
|| type
== AST_FCALL
|| type
== AST_TCALL
) && name_map
.count(str
) > 0)
2767 str
= name_map
[str
];
2769 std::map
<std::string
, std::string
> backup_name_map
;
2771 for (size_t i
= 0; i
< children
.size(); i
++) {
2772 AstNode
*child
= children
[i
];
2773 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
||
2774 child
->type
== AST_FUNCTION
|| child
->type
== AST_TASK
|| child
->type
== AST_CELL
) {
2775 if (backup_name_map
.size() == 0)
2776 backup_name_map
= name_map
;
2777 std::string new_name
= prefix
[0] == '\\' ? prefix
.substr(1) : prefix
;
2778 size_t pos
= child
->str
.rfind('.');
2779 if (pos
== std::string::npos
)
2780 pos
= child
->str
[0] == '\\' && prefix
[0] == '\\' ? 1 : 0;
2783 new_name
= child
->str
.substr(0, pos
) + new_name
+ child
->str
.substr(pos
);
2784 if (new_name
[0] != '$' && new_name
[0] != '\\')
2785 new_name
= prefix
[0] + new_name
;
2786 name_map
[child
->str
] = new_name
;
2787 if (child
->type
== AST_FUNCTION
)
2788 replace_result_wire_name_in_function(child
, child
->str
, new_name
);
2790 child
->str
= new_name
;
2791 current_scope
[new_name
] = child
;
2795 for (size_t i
= 0; i
< children
.size(); i
++) {
2796 AstNode
*child
= children
[i
];
2797 if (child
->type
!= AST_FUNCTION
&& child
->type
!= AST_TASK
&& child
->type
!= AST_PREFIX
)
2798 child
->expand_genblock(index_var
, prefix
, name_map
);
2801 if (backup_name_map
.size() > 0)
2802 name_map
.swap(backup_name_map
);
2805 // rename stuff (used when tasks of functions are instantiated)
2806 void AstNode::replace_ids(const std::string
&prefix
, const std::map
<std::string
, std::string
> &rules
)
2808 if (type
== AST_BLOCK
)
2810 std::map
<std::string
, std::string
> new_rules
= rules
;
2811 std::string new_prefix
= prefix
+ str
;
2813 for (auto child
: children
)
2814 if (child
->type
== AST_WIRE
) {
2815 new_rules
[child
->str
] = new_prefix
+ child
->str
;
2816 child
->str
= new_prefix
+ child
->str
;
2819 for (auto child
: children
)
2820 if (child
->type
!= AST_WIRE
)
2821 child
->replace_ids(new_prefix
, new_rules
);
2825 if (type
== AST_IDENTIFIER
&& rules
.count(str
) > 0)
2826 str
= rules
.at(str
);
2827 for (auto child
: children
)
2828 child
->replace_ids(prefix
, rules
);
2832 // helper function for mem2reg_as_needed_pass1
2833 static void mark_memories_assign_lhs_complex(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
2834 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, AstNode
*that
)
2836 for (auto &child
: that
->children
)
2837 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, child
);
2839 if (that
->type
== AST_IDENTIFIER
&& that
->id2ast
&& that
->id2ast
->type
== AST_MEMORY
) {
2840 AstNode
*mem
= that
->id2ast
;
2841 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_CMPLX_LHS
))
2842 mem2reg_places
[mem
].insert(stringf("%s:%d", that
->filename
.c_str(), that
->linenum
));
2843 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CMPLX_LHS
;
2847 // find memories that should be replaced by registers
2848 void AstNode::mem2reg_as_needed_pass1(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
2849 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, dict
<AstNode
*, uint32_t> &proc_flags
, uint32_t &flags
)
2851 uint32_t children_flags
= 0;
2852 int ignore_children_counter
= 0;
2854 if (type
== AST_ASSIGN
|| type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
)
2856 // mark all memories that are used in a complex expression on the left side of an assignment
2857 for (auto &lhs_child
: children
[0]->children
)
2858 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, lhs_child
);
2860 if (children
[0]->type
== AST_IDENTIFIER
&& children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
)
2862 AstNode
*mem
= children
[0]->id2ast
;
2864 // activate mem2reg if this is assigned in an async proc
2865 if (flags
& AstNode::MEM2REG_FL_ASYNC
) {
2866 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ASYNC
))
2867 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
2868 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ASYNC
;
2871 // remember if this is assigned blocking (=)
2872 if (type
== AST_ASSIGN_EQ
) {
2873 if (!(proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
))
2874 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
2875 proc_flags
[mem
] |= AstNode::MEM2REG_FL_EQ1
;
2878 // remember where this is
2879 if (flags
& MEM2REG_FL_INIT
) {
2880 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_INIT
))
2881 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
2882 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_INIT
;
2884 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ELSE
))
2885 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
2886 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ELSE
;
2890 ignore_children_counter
= 1;
2893 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
)
2895 AstNode
*mem
= id2ast
;
2897 // flag if used after blocking assignment (in same proc)
2898 if ((proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
) && !(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_EQ2
)) {
2899 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
2900 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_EQ2
;
2904 // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg'
2905 if (type
== AST_MEMORY
&& (get_bool_attribute("\\mem2reg") || (flags
& AstNode::MEM2REG_FL_ALL
) || !is_reg
))
2906 mem2reg_candidates
[this] |= AstNode::MEM2REG_FL_FORCED
;
2908 if (type
== AST_MODULE
&& get_bool_attribute("\\mem2reg"))
2909 children_flags
|= AstNode::MEM2REG_FL_ALL
;
2911 dict
<AstNode
*, uint32_t> *proc_flags_p
= NULL
;
2913 if (type
== AST_ALWAYS
) {
2914 int count_edge_events
= 0;
2915 for (auto child
: children
)
2916 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
2917 count_edge_events
++;
2918 if (count_edge_events
!= 1)
2919 children_flags
|= AstNode::MEM2REG_FL_ASYNC
;
2920 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
2923 if (type
== AST_INITIAL
) {
2924 children_flags
|= AstNode::MEM2REG_FL_INIT
;
2925 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
2928 uint32_t backup_flags
= flags
;
2929 flags
|= children_flags
;
2930 log_assert((flags
& ~0x000000ff) == 0);
2932 for (auto child
: children
)
2933 if (ignore_children_counter
> 0)
2934 ignore_children_counter
--;
2935 else if (proc_flags_p
)
2936 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
2938 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
2940 flags
&= ~children_flags
| backup_flags
;
2944 for (auto it
: *proc_flags_p
)
2945 log_assert((it
.second
& ~0xff000000) == 0);
2947 delete proc_flags_p
;
2951 bool AstNode::mem2reg_check(pool
<AstNode
*> &mem2reg_set
)
2953 if (type
!= AST_IDENTIFIER
|| !id2ast
|| !mem2reg_set
.count(id2ast
))
2956 if (children
.empty() || children
[0]->type
!= AST_RANGE
|| GetSize(children
[0]->children
) != 1)
2957 log_error("Invalid array access at %s:%d.\n", filename
.c_str(), linenum
);
2962 void AstNode::mem2reg_remove(pool
<AstNode
*> &mem2reg_set
, vector
<AstNode
*> &delnodes
)
2964 log_assert(mem2reg_set
.count(this) == 0);
2966 if (mem2reg_set
.count(id2ast
))
2969 for (size_t i
= 0; i
< children
.size(); i
++) {
2970 if (mem2reg_set
.count(children
[i
]) > 0) {
2971 delnodes
.push_back(children
[i
]);
2972 children
.erase(children
.begin() + (i
--));
2974 children
[i
]->mem2reg_remove(mem2reg_set
, delnodes
);
2979 // actually replace memories with registers
2980 bool AstNode::mem2reg_as_needed_pass2(pool
<AstNode
*> &mem2reg_set
, AstNode
*mod
, AstNode
*block
, AstNode
*&async_block
)
2982 bool did_something
= false;
2984 if (type
== AST_BLOCK
)
2987 if (type
== AST_FUNCTION
|| type
== AST_TASK
)
2990 if (type
== AST_ASSIGN
&& block
== NULL
&& children
[0]->mem2reg_check(mem2reg_set
))
2992 if (async_block
== NULL
) {
2993 async_block
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
2994 mod
->children
.push_back(async_block
);
2997 AstNode
*newNode
= clone();
2998 newNode
->type
= AST_ASSIGN_EQ
;
2999 async_block
->children
[0]->children
.push_back(newNode
);
3001 newNode
= new AstNode(AST_NONE
);
3002 newNode
->cloneInto(this);
3005 did_something
= true;
3008 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->mem2reg_check(mem2reg_set
) &&
3009 children
[0]->children
[0]->children
[0]->type
!= AST_CONSTANT
)
3011 std::stringstream sstr
;
3012 sstr
<< "$mem2reg_wr$" << children
[0]->str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
3013 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
3015 int mem_width
, mem_size
, addr_bits
;
3016 bool mem_signed
= children
[0]->id2ast
->is_signed
;
3017 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
3019 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
3020 wire_addr
->str
= id_addr
;
3021 wire_addr
->is_reg
= true;
3022 wire_addr
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3023 mod
->children
.push_back(wire_addr
);
3024 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
3026 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
3027 wire_data
->str
= id_data
;
3028 wire_data
->is_reg
= true;
3029 wire_data
->is_signed
= mem_signed
;
3030 wire_data
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3031 mod
->children
.push_back(wire_data
);
3032 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
3034 log_assert(block
!= NULL
);
3035 size_t assign_idx
= 0;
3036 while (assign_idx
< block
->children
.size() && block
->children
[assign_idx
] != this)
3038 log_assert(assign_idx
< block
->children
.size());
3040 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
3041 assign_addr
->children
[0]->str
= id_addr
;
3042 block
->children
.insert(block
->children
.begin()+assign_idx
+1, assign_addr
);
3044 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
3045 case_node
->children
[0]->str
= id_addr
;
3046 for (int i
= 0; i
< mem_size
; i
++) {
3047 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->children
[0]->integer
) != i
)
3049 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
3050 AstNode
*assign_reg
= new AstNode(type
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
3051 if (children
[0]->children
.size() == 2)
3052 assign_reg
->children
[0]->children
.push_back(children
[0]->children
[1]->clone());
3053 assign_reg
->children
[0]->str
= stringf("%s[%d]", children
[0]->str
.c_str(), i
);
3054 assign_reg
->children
[1]->str
= id_data
;
3055 cond_node
->children
[1]->children
.push_back(assign_reg
);
3056 case_node
->children
.push_back(cond_node
);
3058 block
->children
.insert(block
->children
.begin()+assign_idx
+2, case_node
);
3060 children
[0]->delete_children();
3061 children
[0]->range_valid
= false;
3062 children
[0]->id2ast
= NULL
;
3063 children
[0]->str
= id_data
;
3064 type
= AST_ASSIGN_EQ
;
3066 did_something
= true;
3069 if (mem2reg_check(mem2reg_set
))
3071 AstNode
*bit_part_sel
= NULL
;
3072 if (children
.size() == 2)
3073 bit_part_sel
= children
[1]->clone();
3075 if (children
[0]->children
[0]->type
== AST_CONSTANT
)
3077 int id
= children
[0]->children
[0]->integer
;
3078 str
= stringf("%s[%d]", str
.c_str(), id
);
3081 range_valid
= false;
3086 std::stringstream sstr
;
3087 sstr
<< "$mem2reg_rd$" << str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
3088 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
3090 int mem_width
, mem_size
, addr_bits
;
3091 bool mem_signed
= id2ast
->is_signed
;
3092 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
3094 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
3095 wire_addr
->str
= id_addr
;
3096 wire_addr
->is_reg
= true;
3098 wire_addr
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3099 mod
->children
.push_back(wire_addr
);
3100 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
3102 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
3103 wire_data
->str
= id_data
;
3104 wire_data
->is_reg
= true;
3105 wire_data
->is_signed
= mem_signed
;
3107 wire_data
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3108 mod
->children
.push_back(wire_data
);
3109 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
3111 AstNode
*assign_addr
= new AstNode(block
? AST_ASSIGN_EQ
: AST_ASSIGN
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->clone());
3112 assign_addr
->children
[0]->str
= id_addr
;
3114 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
3115 case_node
->children
[0]->str
= id_addr
;
3117 for (int i
= 0; i
< mem_size
; i
++) {
3118 if (children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->integer
) != i
)
3120 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
3121 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
3122 assign_reg
->children
[0]->str
= id_data
;
3123 assign_reg
->children
[1]->str
= stringf("%s[%d]", str
.c_str(), i
);
3124 cond_node
->children
[1]->children
.push_back(assign_reg
);
3125 case_node
->children
.push_back(cond_node
);
3128 std::vector
<RTLIL::State
> x_bits
;
3129 for (int i
= 0; i
< mem_width
; i
++)
3130 x_bits
.push_back(RTLIL::State::Sx
);
3132 AstNode
*cond_node
= new AstNode(AST_COND
, new AstNode(AST_DEFAULT
), new AstNode(AST_BLOCK
));
3133 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), AstNode::mkconst_bits(x_bits
, false));
3134 assign_reg
->children
[0]->str
= id_data
;
3135 cond_node
->children
[1]->children
.push_back(assign_reg
);
3136 case_node
->children
.push_back(cond_node
);
3140 size_t assign_idx
= 0;
3141 while (assign_idx
< block
->children
.size() && !block
->children
[assign_idx
]->contains(this))
3143 log_assert(assign_idx
< block
->children
.size());
3144 block
->children
.insert(block
->children
.begin()+assign_idx
, case_node
);
3145 block
->children
.insert(block
->children
.begin()+assign_idx
, assign_addr
);
3149 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
3150 proc
->children
[0]->children
.push_back(case_node
);
3151 mod
->children
.push_back(proc
);
3152 mod
->children
.push_back(assign_addr
);
3156 range_valid
= false;
3162 children
.push_back(bit_part_sel
);
3164 did_something
= true;
3167 log_assert(id2ast
== NULL
|| mem2reg_set
.count(id2ast
) == 0);
3169 auto children_list
= children
;
3170 for (size_t i
= 0; i
< children_list
.size(); i
++)
3171 if (children_list
[i
]->mem2reg_as_needed_pass2(mem2reg_set
, mod
, block
, async_block
))
3172 did_something
= true;
3174 return did_something
;
3177 // calculate memory dimensions
3178 void AstNode::meminfo(int &mem_width
, int &mem_size
, int &addr_bits
)
3180 log_assert(type
== AST_MEMORY
);
3182 mem_width
= children
[0]->range_left
- children
[0]->range_right
+ 1;
3183 mem_size
= children
[1]->range_left
- children
[1]->range_right
;
3187 mem_size
+= min(children
[1]->range_left
, children
[1]->range_right
) + 1;
3190 while ((1 << addr_bits
) < mem_size
)
3194 bool AstNode::has_const_only_constructs(bool &recommend_const_eval
)
3196 if (type
== AST_FOR
)
3197 recommend_const_eval
= true;
3198 if (type
== AST_WHILE
|| type
== AST_REPEAT
)
3200 if (type
== AST_FCALL
&& current_scope
.count(str
))
3201 if (current_scope
[str
]->has_const_only_constructs(recommend_const_eval
))
3203 for (auto child
: children
)
3204 if (child
->AstNode::has_const_only_constructs(recommend_const_eval
))
3209 // helper function for AstNode::eval_const_function()
3210 void AstNode::replace_variables(std::map
<std::string
, AstNode::varinfo_t
> &variables
, AstNode
*fcall
)
3212 if (type
== AST_IDENTIFIER
&& variables
.count(str
)) {
3213 int offset
= variables
.at(str
).offset
, width
= variables
.at(str
).val
.bits
.size();
3214 if (!children
.empty()) {
3215 if (children
.size() != 1 || children
.at(0)->type
!= AST_RANGE
)
3216 log_error("Memory access in constant function is not supported in %s:%d (called from %s:%d).\n",
3217 filename
.c_str(), linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
3218 children
.at(0)->replace_variables(variables
, fcall
);
3219 while (simplify(true, false, false, 1, -1, false, true)) { }
3220 if (!children
.at(0)->range_valid
)
3221 log_error("Non-constant range in %s:%d (called from %s:%d).\n",
3222 filename
.c_str(), linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
3223 offset
= min(children
.at(0)->range_left
, children
.at(0)->range_right
);
3224 width
= min(std::abs(children
.at(0)->range_left
- children
.at(0)->range_right
) + 1, width
);
3226 offset
-= variables
.at(str
).offset
;
3227 std::vector
<RTLIL::State
> &var_bits
= variables
.at(str
).val
.bits
;
3228 std::vector
<RTLIL::State
> new_bits(var_bits
.begin() + offset
, var_bits
.begin() + offset
+ width
);
3229 AstNode
*newNode
= mkconst_bits(new_bits
, variables
.at(str
).is_signed
);
3230 newNode
->cloneInto(this);
3235 for (auto &child
: children
)
3236 child
->replace_variables(variables
, fcall
);
3239 // evaluate functions with all-const arguments
3240 AstNode
*AstNode::eval_const_function(AstNode
*fcall
)
3242 std::map
<std::string
, AstNode
*> backup_scope
;
3243 std::map
<std::string
, AstNode::varinfo_t
> variables
;
3244 bool delete_temp_block
= false;
3245 AstNode
*block
= NULL
;
3248 for (auto child
: children
)
3250 if (child
->type
== AST_BLOCK
)
3252 log_assert(block
== NULL
);
3257 if (child
->type
== AST_WIRE
)
3259 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
3260 if (!child
->range_valid
)
3261 log_error("Can't determine size of variable %s in %s:%d (called from %s:%d).\n",
3262 child
->str
.c_str(), child
->filename
.c_str(), child
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
3263 variables
[child
->str
].val
= RTLIL::Const(RTLIL::State::Sx
, abs(child
->range_left
- child
->range_right
)+1);
3264 variables
[child
->str
].offset
= min(child
->range_left
, child
->range_right
);
3265 variables
[child
->str
].is_signed
= child
->is_signed
;
3266 if (child
->is_input
&& argidx
< fcall
->children
.size())
3267 variables
[child
->str
].val
= fcall
->children
.at(argidx
++)->bitsAsConst(variables
[child
->str
].val
.bits
.size());
3268 backup_scope
[child
->str
] = current_scope
[child
->str
];
3269 current_scope
[child
->str
] = child
;
3273 log_assert(block
== NULL
);
3274 delete_temp_block
= true;
3275 block
= new AstNode(AST_BLOCK
);
3276 block
->children
.push_back(child
->clone());
3279 log_assert(block
!= NULL
);
3280 log_assert(variables
.count(str
) != 0);
3282 while (!block
->children
.empty())
3284 AstNode
*stmt
= block
->children
.front();
3287 log("-----------------------------------\n");
3288 for (auto &it
: variables
)
3289 log("%20s %40s\n", it
.first
.c_str(), log_signal(it
.second
.val
));
3290 stmt
->dumpAst(NULL
, "stmt> ");
3293 if (stmt
->type
== AST_ASSIGN_EQ
)
3295 if (stmt
->children
.at(0)->type
== AST_IDENTIFIER
&& stmt
->children
.at(0)->children
.size() != 0 &&
3296 stmt
->children
.at(0)->children
.at(0)->type
== AST_RANGE
)
3297 stmt
->children
.at(0)->children
.at(0)->replace_variables(variables
, fcall
);
3298 stmt
->children
.at(1)->replace_variables(variables
, fcall
);
3299 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
3301 if (stmt
->type
!= AST_ASSIGN_EQ
)
3304 if (stmt
->children
.at(1)->type
!= AST_CONSTANT
)
3305 log_error("Non-constant expression in constant function at %s:%d (called from %s:%d). X\n",
3306 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
3308 if (stmt
->children
.at(0)->type
!= AST_IDENTIFIER
)
3309 log_error("Unsupported composite left hand side in constant function at %s:%d (called from %s:%d).\n",
3310 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
3312 if (!variables
.count(stmt
->children
.at(0)->str
))
3313 log_error("Assignment to non-local variable in constant function at %s:%d (called from %s:%d).\n",
3314 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
3316 if (stmt
->children
.at(0)->children
.empty()) {
3317 variables
[stmt
->children
.at(0)->str
].val
= stmt
->children
.at(1)->bitsAsConst(variables
[stmt
->children
.at(0)->str
].val
.bits
.size());
3319 AstNode
*range
= stmt
->children
.at(0)->children
.at(0);
3320 if (!range
->range_valid
)
3321 log_error("Non-constant range in %s:%d (called from %s:%d).\n",
3322 range
->filename
.c_str(), range
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
3323 int offset
= min(range
->range_left
, range
->range_right
);
3324 int width
= std::abs(range
->range_left
- range
->range_right
) + 1;
3325 varinfo_t
&v
= variables
[stmt
->children
.at(0)->str
];
3326 RTLIL::Const r
= stmt
->children
.at(1)->bitsAsConst(v
.val
.bits
.size());
3327 for (int i
= 0; i
< width
; i
++)
3328 v
.val
.bits
.at(i
+offset
-v
.offset
) = r
.bits
.at(i
);
3331 delete block
->children
.front();
3332 block
->children
.erase(block
->children
.begin());
3336 if (stmt
->type
== AST_FOR
)
3338 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(0));
3339 stmt
->children
.at(3)->children
.push_back(stmt
->children
.at(2));
3340 stmt
->children
.erase(stmt
->children
.begin() + 2);
3341 stmt
->children
.erase(stmt
->children
.begin());
3342 stmt
->type
= AST_WHILE
;
3346 if (stmt
->type
== AST_WHILE
)
3348 AstNode
*cond
= stmt
->children
.at(0)->clone();
3349 cond
->replace_variables(variables
, fcall
);
3350 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
3352 if (cond
->type
!= AST_CONSTANT
)
3353 log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
3354 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
3356 if (cond
->asBool()) {
3357 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
3359 delete block
->children
.front();
3360 block
->children
.erase(block
->children
.begin());
3367 if (stmt
->type
== AST_REPEAT
)
3369 AstNode
*num
= stmt
->children
.at(0)->clone();
3370 num
->replace_variables(variables
, fcall
);
3371 while (num
->simplify(true, false, false, 1, -1, false, true)) { }
3373 if (num
->type
!= AST_CONSTANT
)
3374 log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
3375 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
3377 block
->children
.erase(block
->children
.begin());
3378 for (int i
= 0; i
< num
->bitsAsConst().as_int(); i
++)
3379 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
3386 if (stmt
->type
== AST_CASE
)
3388 AstNode
*expr
= stmt
->children
.at(0)->clone();
3389 expr
->replace_variables(variables
, fcall
);
3390 while (expr
->simplify(true, false, false, 1, -1, false, true)) { }
3392 AstNode
*sel_case
= NULL
;
3393 for (size_t i
= 1; i
< stmt
->children
.size(); i
++)
3395 bool found_match
= false;
3396 log_assert(stmt
->children
.at(i
)->type
== AST_COND
|| stmt
->children
.at(i
)->type
== AST_CONDX
|| stmt
->children
.at(i
)->type
== AST_CONDZ
);
3398 if (stmt
->children
.at(i
)->children
.front()->type
== AST_DEFAULT
) {
3399 sel_case
= stmt
->children
.at(i
)->children
.back();
3403 for (size_t j
= 0; j
+1 < stmt
->children
.at(i
)->children
.size() && !found_match
; j
++)
3405 AstNode
*cond
= stmt
->children
.at(i
)->children
.at(j
)->clone();
3406 cond
->replace_variables(variables
, fcall
);
3408 cond
= new AstNode(AST_EQ
, expr
->clone(), cond
);
3409 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
3411 if (cond
->type
!= AST_CONSTANT
)
3412 log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
3413 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
3415 found_match
= cond
->asBool();
3420 sel_case
= stmt
->children
.at(i
)->children
.back();
3425 block
->children
.erase(block
->children
.begin());
3427 block
->children
.insert(block
->children
.begin(), sel_case
->clone());
3433 if (stmt
->type
== AST_BLOCK
)
3435 block
->children
.erase(block
->children
.begin());
3436 block
->children
.insert(block
->children
.begin(), stmt
->children
.begin(), stmt
->children
.end());
3437 stmt
->children
.clear();
3442 log_error("Unsupported language construct in constant function at %s:%d (called from %s:%d).\n",
3443 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
3447 if (delete_temp_block
)
3450 for (auto &it
: backup_scope
)
3451 if (it
.second
== NULL
)
3452 current_scope
.erase(it
.first
);
3454 current_scope
[it
.first
] = it
.second
;
3456 return AstNode::mkconst_bits(variables
.at(str
).val
.bits
, variables
.at(str
).is_signed
);