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 bool deep_recursion_warning
= false;
55 if (recursion_counter
++ == 1000 && deep_recursion_warning
) {
56 log_warning("Deep recursion in AST simplifier.\nDoes this design contain insanely long expressions?\n");
57 deep_recursion_warning
= false;
60 AstNode
*newNode
= NULL
;
61 bool did_something
= false;
64 log("-------------\n");
65 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);
66 log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
67 int(const_fold
), int(at_zero
), int(in_lvalue
), int(stage
), int(width_hint
), int(sign_hint
), int(in_param
));
68 // dumpAst(NULL, "> ");
73 log_assert(type
== AST_MODULE
|| type
== AST_INTERFACE
);
75 deep_recursion_warning
= true;
76 while (simplify(const_fold
, at_zero
, in_lvalue
, 1, width_hint
, sign_hint
, in_param
)) { }
78 if (!flag_nomem2reg
&& !get_bool_attribute("\\nomem2reg"))
80 dict
<AstNode
*, pool
<std::string
>> mem2reg_places
;
81 dict
<AstNode
*, uint32_t> mem2reg_candidates
, dummy_proc_flags
;
82 uint32_t flags
= flag_mem2reg
? AstNode::MEM2REG_FL_ALL
: 0;
83 mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, dummy_proc_flags
, flags
);
85 pool
<AstNode
*> mem2reg_set
;
86 for (auto &it
: mem2reg_candidates
)
88 AstNode
*mem
= it
.first
;
89 uint32_t memflags
= it
.second
;
90 bool this_nomeminit
= flag_nomeminit
;
91 log_assert((memflags
& ~0x00ffff00) == 0);
93 if (mem
->get_bool_attribute("\\nomem2reg"))
96 if (mem
->get_bool_attribute("\\nomeminit") || get_bool_attribute("\\nomeminit"))
97 this_nomeminit
= true;
99 if (memflags
& AstNode::MEM2REG_FL_FORCED
)
100 goto silent_activate
;
102 if (memflags
& AstNode::MEM2REG_FL_EQ2
)
103 goto verbose_activate
;
105 if (memflags
& AstNode::MEM2REG_FL_SET_ASYNC
)
106 goto verbose_activate
;
108 if ((memflags
& AstNode::MEM2REG_FL_SET_INIT
) && (memflags
& AstNode::MEM2REG_FL_SET_ELSE
) && this_nomeminit
)
109 goto verbose_activate
;
111 if (memflags
& AstNode::MEM2REG_FL_CMPLX_LHS
)
112 goto verbose_activate
;
114 if ((memflags
& AstNode::MEM2REG_FL_CONST_LHS
) && !(memflags
& AstNode::MEM2REG_FL_VAR_LHS
))
115 goto verbose_activate
;
117 // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
121 if (mem2reg_set
.count(mem
) == 0) {
122 std::string message
= stringf("Replacing memory %s with list of registers.", mem
->str
.c_str());
123 bool first_element
= true;
124 for (auto &place
: mem2reg_places
[it
.first
]) {
125 message
+= stringf("%s%s", first_element
? " See " : ", ", place
.c_str());
126 first_element
= false;
128 log_warning("%s\n", message
.c_str());
132 // log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
133 mem2reg_set
.insert(mem
);
136 for (auto node
: mem2reg_set
)
138 int mem_width
, mem_size
, addr_bits
;
139 node
->meminfo(mem_width
, mem_size
, addr_bits
);
141 int data_range_left
= node
->children
[0]->range_left
;
142 int data_range_right
= node
->children
[0]->range_right
;
144 if (node
->children
[0]->range_swapped
)
145 std::swap(data_range_left
, data_range_right
);
147 for (int i
= 0; i
< mem_size
; i
++) {
148 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
149 mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
150 reg
->str
= stringf("%s[%d]", node
->str
.c_str(), i
);
152 reg
->is_signed
= node
->is_signed
;
153 children
.push_back(reg
);
154 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
158 AstNode
*async_block
= NULL
;
159 while (mem2reg_as_needed_pass2(mem2reg_set
, this, NULL
, async_block
)) { }
161 vector
<AstNode
*> delnodes
;
162 mem2reg_remove(mem2reg_set
, delnodes
);
164 for (auto node
: delnodes
)
168 while (simplify(const_fold
, at_zero
, in_lvalue
, 2, width_hint
, sign_hint
, in_param
)) { }
173 current_filename
= filename
;
174 set_line_num(linenum
);
176 // we do not look inside a task or function
177 // (but as soon as a task or function is instantiated we process the generated AST as usual)
178 if (type
== AST_FUNCTION
|| type
== AST_TASK
) {
183 // deactivate all calls to non-synthesis system tasks
184 // note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
185 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && (str
== "$strobe" || str
== "$monitor" || str
== "$time" ||
186 str
== "$dumpfile" || str
== "$dumpvars" || str
== "$dumpon" || str
== "$dumpoff" || str
== "$dumpall")) {
187 log_file_warning(filename
, linenum
, "Ignoring call to system %s %s.\n", type
== AST_FCALL
? "function" : "task", str
.c_str());
192 if ((type
== AST_TCALL
) && (str
== "$display" || str
== "$write") && (!current_always
|| current_always
->type
!= AST_INITIAL
)) {
193 log_file_warning(filename
, linenum
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
198 // print messages if this a call to $display() or $write()
199 // This code implements only a small subset of Verilog-2005 $display() format specifiers,
200 // but should be good enough for most uses
201 if ((type
== AST_TCALL
) && ((str
== "$display") || (str
== "$write")))
203 int nargs
= GetSize(children
);
205 log_file_error(filename
, linenum
, "System task `%s' got %d arguments, expected >= 1.\n",
206 str
.c_str(), int(children
.size()));
208 // First argument is the format string
209 AstNode
*node_string
= children
[0];
210 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
211 if (node_string
->type
!= AST_CONSTANT
)
212 log_file_error(filename
, linenum
, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str
.c_str());
213 std::string sformat
= node_string
->bitsAsConst().decode_string();
215 // Other arguments are placeholders. Process the string as we go through it
218 for (size_t i
= 0; i
< sformat
.length(); i
++)
221 if (sformat
[i
] == '%')
223 // If there's no next character, that's a problem
224 if (i
+1 >= sformat
.length())
225 log_file_error(filename
, linenum
, "System task `%s' called with `%%' at end of string.\n", str
.c_str());
227 char cformat
= sformat
[++i
];
229 // %% is special, does not need a matching argument
236 // Simplify the argument
237 AstNode
*node_arg
= nullptr;
239 // Everything from here on depends on the format specifier
248 if (next_arg
>= GetSize(children
))
249 log_file_error(filename
, linenum
, "Missing argument for %%%c format specifier in system task `%s'.\n",
250 cformat
, str
.c_str());
252 node_arg
= children
[next_arg
++];
253 while (node_arg
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
254 if (node_arg
->type
!= AST_CONSTANT
)
255 log_file_error(filename
, linenum
, "Failed to evaluate system task `%s' with non-constant argument.\n", str
.c_str());
263 log_file_error(filename
, linenum
, "System task `%s' called with invalid/unsupported format specifier.\n", str
.c_str());
271 sout
+= node_arg
->bitsAsConst().decode_string();
278 snprintf(tmp
, sizeof(tmp
), "%d", node_arg
->bitsAsConst().as_int());
287 snprintf(tmp
, sizeof(tmp
), "%x", node_arg
->bitsAsConst().as_int());
294 sout
+= log_id(current_module
->name
);
302 // not a format specifier
307 // Finally, print the message (only include a \n for $display, not for $write)
308 log("%s", sout
.c_str());
309 if (str
== "$display")
315 // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
316 if (type
== AST_WIRE
|| type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_RANGE
|| type
== AST_PREFIX
)
318 if (type
== AST_IDENTIFIER
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
))
321 // in certain cases a function must be evaluated constant. this is what in_param controls.
322 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_PREFIX
)
325 std::map
<std::string
, AstNode
*> backup_scope
;
327 // create name resolution entries for all objects with names
328 // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
329 if (type
== AST_MODULE
) {
330 current_scope
.clear();
331 std::map
<std::string
, AstNode
*> this_wire_scope
;
332 for (size_t i
= 0; i
< children
.size(); i
++) {
333 AstNode
*node
= children
[i
];
334 if (node
->type
== AST_WIRE
) {
335 if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
336 for (auto c
: node
->children
[0]->children
) {
337 if (!c
->is_simple_const_expr()) {
338 if (attributes
.count("\\dynports"))
339 delete attributes
.at("\\dynports");
340 attributes
["\\dynports"] = AstNode::mkconst_int(1, true);
344 if (this_wire_scope
.count(node
->str
) > 0) {
345 AstNode
*first_node
= this_wire_scope
[node
->str
];
346 if (first_node
->is_input
&& node
->is_reg
)
347 goto wires_are_incompatible
;
348 if (!node
->is_input
&& !node
->is_output
&& node
->is_reg
&& node
->children
.size() == 0)
349 goto wires_are_compatible
;
350 if (first_node
->children
.size() == 0 && node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
351 AstNode
*r
= node
->children
[0];
352 if (r
->range_valid
&& r
->range_left
== 0 && r
->range_right
== 0) {
354 node
->children
.pop_back();
357 if (first_node
->children
.size() != node
->children
.size())
358 goto wires_are_incompatible
;
359 for (size_t j
= 0; j
< node
->children
.size(); j
++) {
360 AstNode
*n1
= first_node
->children
[j
], *n2
= node
->children
[j
];
361 if (n1
->type
== AST_RANGE
&& n2
->type
== AST_RANGE
&& n1
->range_valid
&& n2
->range_valid
) {
362 if (n1
->range_left
!= n2
->range_left
)
363 goto wires_are_incompatible
;
364 if (n1
->range_right
!= n2
->range_right
)
365 goto wires_are_incompatible
;
366 } else if (*n1
!= *n2
)
367 goto wires_are_incompatible
;
369 if (first_node
->range_left
!= node
->range_left
)
370 goto wires_are_incompatible
;
371 if (first_node
->range_right
!= node
->range_right
)
372 goto wires_are_incompatible
;
373 if (first_node
->port_id
== 0 && (node
->is_input
|| node
->is_output
))
374 goto wires_are_incompatible
;
375 wires_are_compatible
:
377 first_node
->is_input
= true;
379 first_node
->is_output
= true;
381 first_node
->is_reg
= true;
383 first_node
->is_logic
= true;
385 first_node
->is_signed
= true;
386 for (auto &it
: node
->attributes
) {
387 if (first_node
->attributes
.count(it
.first
) > 0)
388 delete first_node
->attributes
[it
.first
];
389 first_node
->attributes
[it
.first
] = it
.second
->clone();
391 children
.erase(children
.begin()+(i
--));
392 did_something
= true;
395 wires_are_incompatible
:
397 log_file_error(filename
, linenum
, "Incompatible re-declaration of wire %s.\n", node
->str
.c_str());
400 this_wire_scope
[node
->str
] = node
;
402 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
403 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
|| node
->type
== AST_CELL
) {
404 backup_scope
[node
->str
] = current_scope
[node
->str
];
405 current_scope
[node
->str
] = node
;
408 for (size_t i
= 0; i
< children
.size(); i
++) {
409 AstNode
*node
= children
[i
];
410 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_MEMORY
)
411 while (node
->simplify(true, false, false, 1, -1, false, node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
))
412 did_something
= true;
416 auto backup_current_block
= current_block
;
417 auto backup_current_block_child
= current_block_child
;
418 auto backup_current_top_block
= current_top_block
;
419 auto backup_current_always
= current_always
;
420 auto backup_current_always_clocked
= current_always_clocked
;
422 if (type
== AST_ALWAYS
|| type
== AST_INITIAL
)
424 if (current_always
!= nullptr)
425 log_file_error(filename
, linenum
, "Invalid nesting of always blocks and/or initializations.\n");
427 current_always
= this;
428 current_always_clocked
= false;
430 if (type
== AST_ALWAYS
)
431 for (auto child
: children
) {
432 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
433 current_always_clocked
= true;
434 if (child
->type
== AST_EDGE
&& GetSize(child
->children
) == 1 &&
435 child
->children
[0]->type
== AST_IDENTIFIER
&& child
->children
[0]->str
== "\\$global_clock")
436 current_always_clocked
= true;
440 int backup_width_hint
= width_hint
;
441 bool backup_sign_hint
= sign_hint
;
443 bool detect_width_simple
= false;
444 bool child_0_is_self_determined
= false;
445 bool child_1_is_self_determined
= false;
446 bool child_2_is_self_determined
= false;
447 bool children_are_self_determined
= false;
448 bool reset_width_after_children
= false;
455 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, true, stage
, -1, false, in_param
) == true)
456 did_something
= true;
457 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
) == true)
458 did_something
= true;
459 children
[0]->detectSignWidth(backup_width_hint
, backup_sign_hint
);
460 children
[1]->detectSignWidth(width_hint
, sign_hint
);
461 width_hint
= max(width_hint
, backup_width_hint
);
462 child_0_is_self_determined
= true;
463 // test only once, before optimizations and memory mappings but after assignment LHS was mapped to an identifier
464 if (children
[0]->id2ast
&& !children
[0]->was_checked
) {
465 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->id2ast
->is_logic
)
466 children
[0]->id2ast
->is_reg
= true; // if logic type is used in a block asignment
467 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && !children
[0]->id2ast
->is_reg
)
468 log_warning("wire '%s' is assigned in a block at %s:%d.\n", children
[0]->str
.c_str(), filename
.c_str(), linenum
);
469 if (type
== AST_ASSIGN
&& children
[0]->id2ast
->is_reg
) {
470 bool is_rand_reg
= false;
471 if (children
[1]->type
== AST_FCALL
) {
472 if (children
[1]->str
== "\\$anyconst")
474 if (children
[1]->str
== "\\$anyseq")
476 if (children
[1]->str
== "\\$allconst")
478 if (children
[1]->str
== "\\$allseq")
482 log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children
[0]->str
.c_str(), filename
.c_str(), linenum
);
484 children
[0]->was_checked
= true;
490 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, true) == true)
491 did_something
= true;
492 children
[0]->detectSignWidth(width_hint
, sign_hint
);
493 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
494 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, true) == true)
495 did_something
= true;
496 if (!children
[1]->range_valid
)
497 log_file_error(filename
, linenum
, "Non-constant width range on parameter decl.\n");
498 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
504 case AST_TO_UNSIGNED
:
510 case AST_REDUCE_XNOR
:
511 case AST_REDUCE_BOOL
:
512 detect_width_simple
= true;
513 children_are_self_determined
= true;
528 detect_width_simple
= true;
532 case AST_SHIFT_RIGHT
:
533 case AST_SHIFT_SLEFT
:
534 case AST_SHIFT_SRIGHT
:
536 detect_width_simple
= true;
537 child_1_is_self_determined
= true;
550 for (auto child
: children
) {
551 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
552 did_something
= true;
553 child
->detectSignWidthWorker(width_hint
, sign_hint
);
555 reset_width_after_children
= true;
561 detect_width_simple
= true;
562 children_are_self_determined
= true;
566 detect_width_simple
= true;
567 child_0_is_self_determined
= true;
571 detect_width_simple
= true;
572 children_are_self_determined
= true;
577 children_are_self_determined
= true;
585 if (detect_width_simple
&& width_hint
< 0) {
586 if (type
== AST_REPLICATE
)
587 while (children
[0]->simplify(true, false, in_lvalue
, stage
, -1, false, true) == true)
588 did_something
= true;
589 for (auto child
: children
)
590 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
591 did_something
= true;
592 detectSignWidth(width_hint
, sign_hint
);
595 if (type
== AST_FCALL
&& str
== "\\$past")
596 detectSignWidth(width_hint
, sign_hint
);
598 if (type
== AST_TERNARY
) {
599 int width_hint_left
, width_hint_right
;
600 bool sign_hint_left
, sign_hint_right
;
601 bool found_real_left
, found_real_right
;
602 children
[1]->detectSignWidth(width_hint_left
, sign_hint_left
, &found_real_left
);
603 children
[2]->detectSignWidth(width_hint_right
, sign_hint_right
, &found_real_right
);
604 if (found_real_left
|| found_real_right
) {
605 child_1_is_self_determined
= true;
606 child_2_is_self_determined
= true;
610 if (type
== AST_CONDX
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
611 for (auto &bit
: children
.at(0)->bits
)
612 if (bit
== State::Sz
|| bit
== State::Sx
)
616 if (type
== AST_CONDZ
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
617 for (auto &bit
: children
.at(0)->bits
)
618 if (bit
== State::Sz
)
622 if (const_fold
&& type
== AST_CASE
)
624 while (children
[0]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
625 if (children
[0]->type
== AST_CONSTANT
&& children
[0]->bits_only_01()) {
626 std::vector
<AstNode
*> new_children
;
627 new_children
.push_back(children
[0]);
628 for (int i
= 1; i
< GetSize(children
); i
++) {
629 AstNode
*child
= children
[i
];
630 log_assert(child
->type
== AST_COND
|| child
->type
== AST_CONDX
|| child
->type
== AST_CONDZ
);
631 for (auto v
: child
->children
) {
632 if (v
->type
== AST_DEFAULT
)
633 goto keep_const_cond
;
634 if (v
->type
== AST_BLOCK
)
636 while (v
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
637 if (v
->type
== AST_CONSTANT
&& v
->bits_only_01()) {
638 if (v
->bits
== children
[0]->bits
) {
639 while (i
+1 < GetSize(children
))
640 delete children
[++i
];
641 goto keep_const_cond
;
645 goto keep_const_cond
;
649 new_children
.push_back(child
);
653 new_children
.swap(children
);
657 // simplify all children first
658 // (iterate by index as e.g. auto wires can add new children in the process)
659 for (size_t i
= 0; i
< children
.size(); i
++) {
660 bool did_something_here
= true;
661 bool backup_flag_autowire
= flag_autowire
;
662 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && i
>= 3)
664 if ((type
== AST_GENIF
|| type
== AST_GENCASE
) && i
>= 1)
666 if (type
== AST_GENBLOCK
)
668 if (type
== AST_BLOCK
&& !str
.empty())
670 if (type
== AST_PREFIX
&& i
>= 1)
672 if (type
== AST_DEFPARAM
&& i
== 0)
673 flag_autowire
= true;
674 while (did_something_here
&& i
< children
.size()) {
675 bool const_fold_here
= const_fold
, in_lvalue_here
= in_lvalue
;
676 int width_hint_here
= width_hint
;
677 bool sign_hint_here
= sign_hint
;
678 bool in_param_here
= in_param
;
679 if (i
== 0 && (type
== AST_REPLICATE
|| type
== AST_WIRE
))
680 const_fold_here
= true, in_param_here
= true;
681 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
)
682 const_fold_here
= true;
683 if (i
== 0 && (type
== AST_ASSIGN
|| type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
))
684 in_lvalue_here
= true;
685 if (type
== AST_BLOCK
) {
686 current_block
= this;
687 current_block_child
= children
[i
];
689 if ((type
== AST_ALWAYS
|| type
== AST_INITIAL
) && children
[i
]->type
== AST_BLOCK
)
690 current_top_block
= children
[i
];
691 if (i
== 0 && child_0_is_self_determined
)
692 width_hint_here
= -1, sign_hint_here
= false;
693 if (i
== 1 && child_1_is_self_determined
)
694 width_hint_here
= -1, sign_hint_here
= false;
695 if (i
== 2 && child_2_is_self_determined
)
696 width_hint_here
= -1, sign_hint_here
= false;
697 if (children_are_self_determined
)
698 width_hint_here
= -1, sign_hint_here
= false;
699 did_something_here
= children
[i
]->simplify(const_fold_here
, at_zero
, in_lvalue_here
, stage
, width_hint_here
, sign_hint_here
, in_param_here
);
700 if (did_something_here
)
701 did_something
= true;
703 if (stage
== 2 && children
[i
]->type
== AST_INITIAL
&& current_ast_mod
!= this) {
704 current_ast_mod
->children
.push_back(children
[i
]);
705 children
.erase(children
.begin() + (i
--));
706 did_something
= true;
708 flag_autowire
= backup_flag_autowire
;
710 for (auto &attr
: attributes
) {
711 while (attr
.second
->simplify(true, false, false, stage
, -1, false, true))
712 did_something
= true;
715 if (reset_width_after_children
) {
716 width_hint
= backup_width_hint
;
717 sign_hint
= backup_sign_hint
;
719 detectSignWidth(width_hint
, sign_hint
);
722 current_block
= backup_current_block
;
723 current_block_child
= backup_current_block_child
;
724 current_top_block
= backup_current_top_block
;
725 current_always
= backup_current_always
;
726 current_always_clocked
= backup_current_always_clocked
;
728 for (auto it
= backup_scope
.begin(); it
!= backup_scope
.end(); it
++) {
729 if (it
->second
== NULL
)
730 current_scope
.erase(it
->first
);
732 current_scope
[it
->first
] = it
->second
;
735 current_filename
= filename
;
736 set_line_num(linenum
);
738 if (type
== AST_MODULE
)
739 current_scope
.clear();
741 // convert defparam nodes to cell parameters
742 if (type
== AST_DEFPARAM
&& !children
.empty())
744 if (children
[0]->type
!= AST_IDENTIFIER
)
745 log_file_error(filename
, linenum
, "Module name in defparam contains non-constant expressions!\n");
747 string modname
, paramname
= children
[0]->str
;
749 size_t pos
= paramname
.rfind('.');
751 while (pos
!= 0 && pos
!= std::string::npos
)
753 modname
= paramname
.substr(0, pos
);
755 if (current_scope
.count(modname
))
758 pos
= paramname
.rfind('.', pos
- 1);
761 if (pos
== std::string::npos
)
762 log_file_error(filename
, linenum
, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname
).c_str());
764 paramname
= "\\" + paramname
.substr(pos
+1);
766 if (current_scope
.at(modname
)->type
!= AST_CELL
)
767 log_file_error(filename
, linenum
, "Defparam argument `%s . %s` does not match a cell!\n",
768 RTLIL::unescape_id(modname
).c_str(), RTLIL::unescape_id(paramname
).c_str());
770 AstNode
*paraset
= new AstNode(AST_PARASET
, children
[1]->clone(), GetSize(children
) > 2 ? children
[2]->clone() : NULL
);
771 paraset
->str
= paramname
;
773 AstNode
*cell
= current_scope
.at(modname
);
774 cell
->children
.insert(cell
->children
.begin() + 1, paraset
);
778 // resolve constant prefixes
779 if (type
== AST_PREFIX
) {
780 if (children
[0]->type
!= AST_CONSTANT
) {
781 // dumpAst(NULL, "> ");
782 log_file_error(filename
, linenum
, "Index in generate block prefix syntax is not constant!\n");
784 if (children
[1]->type
== AST_PREFIX
)
785 children
[1]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
);
786 log_assert(children
[1]->type
== AST_IDENTIFIER
);
787 newNode
= children
[1]->clone();
788 const char *second_part
= children
[1]->str
.c_str();
789 if (second_part
[0] == '\\')
791 newNode
->str
= stringf("%s[%d].%s", str
.c_str(), children
[0]->integer
, second_part
);
795 // evaluate TO_BITS nodes
796 if (type
== AST_TO_BITS
) {
797 if (children
[0]->type
!= AST_CONSTANT
)
798 log_file_error(filename
, linenum
, "Left operand of to_bits expression is not constant!\n");
799 if (children
[1]->type
!= AST_CONSTANT
)
800 log_file_error(filename
, linenum
, "Right operand of to_bits expression is not constant!\n");
801 RTLIL::Const new_value
= children
[1]->bitsAsConst(children
[0]->bitsAsConst().as_int(), children
[1]->is_signed
);
802 newNode
= mkconst_bits(new_value
.bits
, children
[1]->is_signed
);
806 // annotate constant ranges
807 if (type
== AST_RANGE
) {
808 bool old_range_valid
= range_valid
;
810 range_swapped
= false;
813 log_assert(children
.size() >= 1);
814 if (children
[0]->type
== AST_CONSTANT
) {
816 range_left
= children
[0]->integer
;
817 if (children
.size() == 1)
818 range_right
= range_left
;
820 if (children
.size() >= 2) {
821 if (children
[1]->type
== AST_CONSTANT
)
822 range_right
= children
[1]->integer
;
826 if (old_range_valid
!= range_valid
)
827 did_something
= true;
828 if (range_valid
&& range_left
>= 0 && range_right
> range_left
) {
829 int tmp
= range_right
;
830 range_right
= range_left
;
832 range_swapped
= true;
836 // annotate wires with their ranges
837 if (type
== AST_WIRE
) {
838 if (children
.size() > 0) {
839 if (children
[0]->range_valid
) {
841 did_something
= true;
843 range_swapped
= children
[0]->range_swapped
;
844 range_left
= children
[0]->range_left
;
845 range_right
= children
[0]->range_right
;
849 did_something
= true;
851 range_swapped
= false;
857 // resolve multiranges on memory decl
858 if (type
== AST_MEMORY
&& children
.size() > 1 && children
[1]->type
== AST_MULTIRANGE
)
861 multirange_dimensions
.clear();
862 for (auto range
: children
[1]->children
) {
863 if (!range
->range_valid
)
864 log_file_error(filename
, linenum
, "Non-constant range on memory decl.\n");
865 multirange_dimensions
.push_back(min(range
->range_left
, range
->range_right
));
866 multirange_dimensions
.push_back(max(range
->range_left
, range
->range_right
) - min(range
->range_left
, range
->range_right
) + 1);
867 total_size
*= multirange_dimensions
.back();
870 children
[1] = new AstNode(AST_RANGE
, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size
-1, true));
871 did_something
= true;
874 // resolve multiranges on memory access
875 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
&& children
.size() > 0 && children
[0]->type
== AST_MULTIRANGE
)
877 AstNode
*index_expr
= nullptr;
879 for (int i
= 0; 2*i
< GetSize(id2ast
->multirange_dimensions
); i
++)
881 if (GetSize(children
[0]->children
) < i
)
882 log_file_error(filename
, linenum
, "Insufficient number of array indices for %s.\n", log_id(str
));
884 AstNode
*new_index_expr
= children
[0]->children
[i
]->children
.at(0)->clone();
886 if (id2ast
->multirange_dimensions
[2*i
])
887 new_index_expr
= new AstNode(AST_SUB
, new_index_expr
, AstNode::mkconst_int(id2ast
->multirange_dimensions
[2*i
], true));
890 index_expr
= new_index_expr
;
892 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
);
895 for (int i
= GetSize(id2ast
->multirange_dimensions
)/2; i
< GetSize(children
[0]->children
); i
++)
896 children
.push_back(children
[0]->children
[i
]->clone());
899 if (index_expr
== nullptr)
900 children
.erase(children
.begin());
902 children
[0] = new AstNode(AST_RANGE
, index_expr
);
904 did_something
= true;
907 // trim/extend parameters
908 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
) {
909 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
910 if (!children
[1]->range_valid
)
911 log_file_error(filename
, linenum
, "Non-constant width range on parameter decl.\n");
912 int width
= std::abs(children
[1]->range_left
- children
[1]->range_right
) + 1;
913 if (children
[0]->type
== AST_REALVALUE
) {
914 RTLIL::Const constvalue
= children
[0]->realAsConst(width
);
915 log_file_warning(filename
, linenum
, "converting real value %e to binary %s.\n",
916 children
[0]->realvalue
, log_signal(constvalue
));
918 children
[0] = mkconst_bits(constvalue
.bits
, sign_hint
);
919 did_something
= true;
921 if (children
[0]->type
== AST_CONSTANT
) {
922 if (width
!= int(children
[0]->bits
.size())) {
923 RTLIL::SigSpec
sig(children
[0]->bits
);
924 sig
.extend_u0(width
, children
[0]->is_signed
);
925 AstNode
*old_child_0
= children
[0];
926 children
[0] = mkconst_bits(sig
.as_const().bits
, is_signed
);
929 children
[0]->is_signed
= is_signed
;
932 range_swapped
= children
[1]->range_swapped
;
933 range_left
= children
[1]->range_left
;
934 range_right
= children
[1]->range_right
;
936 if (children
.size() > 1 && children
[1]->type
== AST_REALVALUE
&& children
[0]->type
== AST_CONSTANT
) {
937 double as_realvalue
= children
[0]->asReal(sign_hint
);
939 children
[0] = new AstNode(AST_REALVALUE
);
940 children
[0]->realvalue
= as_realvalue
;
941 did_something
= true;
945 // annotate identifiers using scope resolution and create auto-wires as needed
946 if (type
== AST_IDENTIFIER
) {
947 if (current_scope
.count(str
) == 0) {
948 for (auto node
: current_ast_mod
->children
) {
949 if ((node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
950 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
) && str
== node
->str
) {
951 current_scope
[node
->str
] = node
;
956 if (current_scope
.count(str
) == 0) {
957 if (flag_autowire
|| str
== "\\$global_clock") {
958 AstNode
*auto_wire
= new AstNode(AST_AUTOWIRE
);
959 auto_wire
->str
= str
;
960 current_ast_mod
->children
.push_back(auto_wire
);
961 current_scope
[str
] = auto_wire
;
962 did_something
= true;
964 log_file_error(filename
, linenum
, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str
.c_str());
967 if (id2ast
!= current_scope
[str
]) {
968 id2ast
= current_scope
[str
];
969 did_something
= true;
973 // split memory access with bit select to individual statements
974 if (type
== AST_IDENTIFIER
&& children
.size() == 2 && children
[0]->type
== AST_RANGE
&& children
[1]->type
== AST_RANGE
&& !in_lvalue
)
976 if (id2ast
== NULL
|| id2ast
->type
!= AST_MEMORY
|| children
[0]->children
.size() != 1)
977 log_file_error(filename
, linenum
, "Invalid bit-select on memory access!\n");
979 int mem_width
, mem_size
, addr_bits
;
980 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
982 int data_range_left
= id2ast
->children
[0]->range_left
;
983 int data_range_right
= id2ast
->children
[0]->range_right
;
985 if (id2ast
->children
[0]->range_swapped
)
986 std::swap(data_range_left
, data_range_right
);
988 std::stringstream sstr
;
989 sstr
<< "$mem2bits$" << str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
990 std::string wire_id
= sstr
.str();
992 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
995 wire
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
996 current_ast_mod
->children
.push_back(wire
);
997 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
999 AstNode
*data
= clone();
1000 delete data
->children
[1];
1001 data
->children
.pop_back();
1003 AstNode
*assign
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), data
);
1004 assign
->children
[0]->str
= wire_id
;
1005 assign
->children
[0]->was_checked
= true;
1009 size_t assign_idx
= 0;
1010 while (assign_idx
< current_block
->children
.size() && current_block
->children
[assign_idx
] != current_block_child
)
1012 log_assert(assign_idx
< current_block
->children
.size());
1013 current_block
->children
.insert(current_block
->children
.begin()+assign_idx
, assign
);
1014 wire
->is_reg
= true;
1018 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
1019 proc
->children
[0]->children
.push_back(assign
);
1020 current_ast_mod
->children
.push_back(proc
);
1023 newNode
= new AstNode(AST_IDENTIFIER
, children
[1]->clone());
1024 newNode
->str
= wire_id
;
1025 newNode
->id2ast
= wire
;
1029 if (type
== AST_WHILE
)
1030 log_file_error(filename
, linenum
, "While loops are only allowed in constant functions!\n");
1032 if (type
== AST_REPEAT
)
1034 AstNode
*count
= children
[0];
1035 AstNode
*body
= children
[1];
1037 // eval count expression
1038 while (count
->simplify(true, false, false, stage
, 32, true, false)) { }
1040 if (count
->type
!= AST_CONSTANT
)
1041 log_file_error(filename
, linenum
, "Repeat loops outside must have constant repeat counts!\n");
1043 // convert to a block with the body repeated n times
1046 for (int i
= 0; i
< count
->bitsAsConst().as_int(); i
++)
1047 children
.insert(children
.begin(), body
->clone());
1051 did_something
= true;
1054 // unroll for loops and generate-for blocks
1055 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && children
.size() != 0)
1057 AstNode
*init_ast
= children
[0];
1058 AstNode
*while_ast
= children
[1];
1059 AstNode
*next_ast
= children
[2];
1060 AstNode
*body_ast
= children
[3];
1062 while (body_ast
->type
== AST_GENBLOCK
&& body_ast
->str
.empty() &&
1063 body_ast
->children
.size() == 1 && body_ast
->children
.at(0)->type
== AST_GENBLOCK
)
1064 body_ast
= body_ast
->children
.at(0);
1066 if (init_ast
->type
!= AST_ASSIGN_EQ
)
1067 log_file_error(filename
, linenum
, "Unsupported 1st expression of generate for-loop!\n");
1068 if (next_ast
->type
!= AST_ASSIGN_EQ
)
1069 log_file_error(filename
, linenum
, "Unsupported 3rd expression of generate for-loop!\n");
1071 if (type
== AST_GENFOR
) {
1072 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
1073 log_file_error(filename
, linenum
, "Left hand side of 1st expression of generate for-loop is not a gen var!\n");
1074 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
1075 log_file_error(filename
, linenum
, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n");
1077 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1078 log_file_error(filename
, linenum
, "Left hand side of 1st expression of generate for-loop is not a register!\n");
1079 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1080 log_file_error(filename
, linenum
, "Left hand side of 3rd expression of generate for-loop is not a register!\n");
1083 if (init_ast
->children
[0]->id2ast
!= next_ast
->children
[0]->id2ast
)
1084 log_file_error(filename
, linenum
, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n");
1086 // eval 1st expression
1087 AstNode
*varbuf
= init_ast
->children
[1]->clone();
1089 int expr_width_hint
= -1;
1090 bool expr_sign_hint
= true;
1091 varbuf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1092 while (varbuf
->simplify(true, false, false, stage
, 32, true, false)) { }
1095 if (varbuf
->type
!= AST_CONSTANT
)
1096 log_file_error(filename
, linenum
, "Right hand side of 1st expression of generate for-loop is not constant!\n");
1098 varbuf
= new AstNode(AST_LOCALPARAM
, varbuf
);
1099 varbuf
->str
= init_ast
->children
[0]->str
;
1101 AstNode
*backup_scope_varbuf
= current_scope
[varbuf
->str
];
1102 current_scope
[varbuf
->str
] = varbuf
;
1104 size_t current_block_idx
= 0;
1105 if (type
== AST_FOR
) {
1106 while (current_block_idx
< current_block
->children
.size() &&
1107 current_block
->children
[current_block_idx
] != current_block_child
)
1108 current_block_idx
++;
1113 // eval 2nd expression
1114 AstNode
*buf
= while_ast
->clone();
1116 int expr_width_hint
= -1;
1117 bool expr_sign_hint
= true;
1118 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1119 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, false)) { }
1122 if (buf
->type
!= AST_CONSTANT
)
1123 log_file_error(filename
, linenum
, "2nd expression of generate for-loop is not constant!\n");
1125 if (buf
->integer
== 0) {
1132 int index
= varbuf
->children
[0]->integer
;
1133 if (body_ast
->type
== AST_GENBLOCK
)
1134 buf
= body_ast
->clone();
1136 buf
= new AstNode(AST_GENBLOCK
, body_ast
->clone());
1137 if (buf
->str
.empty()) {
1138 std::stringstream sstr
;
1139 sstr
<< "$genblock$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1140 buf
->str
= sstr
.str();
1142 std::map
<std::string
, std::string
> name_map
;
1143 std::stringstream sstr
;
1144 sstr
<< buf
->str
<< "[" << index
<< "].";
1145 buf
->expand_genblock(varbuf
->str
, sstr
.str(), name_map
);
1147 if (type
== AST_GENFOR
) {
1148 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1149 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1150 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1153 for (size_t i
= 0; i
< buf
->children
.size(); i
++)
1154 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
->children
[i
]);
1156 buf
->children
.clear();
1159 // eval 3rd expression
1160 buf
= next_ast
->children
[1]->clone();
1162 int expr_width_hint
= -1;
1163 bool expr_sign_hint
= true;
1164 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1165 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, true)) { }
1168 if (buf
->type
!= AST_CONSTANT
)
1169 log_file_error(filename
, linenum
, "Right hand side of 3rd expression of generate for-loop is not constant!\n");
1171 delete varbuf
->children
[0];
1172 varbuf
->children
[0] = buf
;
1176 if (type
== AST_FOR
) {
1177 AstNode
*buf
= next_ast
->clone();
1178 delete buf
->children
[1];
1179 buf
->children
[1] = varbuf
->children
[0]->clone();
1180 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
);
1184 current_scope
[varbuf
->str
] = backup_scope_varbuf
;
1187 did_something
= true;
1190 // check for local objects in unnamed block
1191 if (type
== AST_BLOCK
&& str
.empty())
1193 for (size_t i
= 0; i
< children
.size(); i
++)
1194 if (children
[i
]->type
== AST_WIRE
|| children
[i
]->type
== AST_MEMORY
|| children
[i
]->type
== AST_PARAMETER
|| children
[i
]->type
== AST_LOCALPARAM
)
1195 log_file_error(children
[i
]->filename
, children
[i
]->linenum
, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
1198 // transform block with name
1199 if (type
== AST_BLOCK
&& !str
.empty())
1201 std::map
<std::string
, std::string
> name_map
;
1202 expand_genblock(std::string(), str
+ ".", name_map
);
1204 std::vector
<AstNode
*> new_children
;
1205 for (size_t i
= 0; i
< children
.size(); i
++)
1206 if (children
[i
]->type
== AST_WIRE
|| children
[i
]->type
== AST_MEMORY
|| children
[i
]->type
== AST_PARAMETER
|| children
[i
]->type
== AST_LOCALPARAM
) {
1207 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1208 current_ast_mod
->children
.push_back(children
[i
]);
1209 current_scope
[children
[i
]->str
] = children
[i
];
1211 new_children
.push_back(children
[i
]);
1213 children
.swap(new_children
);
1214 did_something
= true;
1218 // simplify unconditional generate block
1219 if (type
== AST_GENBLOCK
&& children
.size() != 0)
1222 std::map
<std::string
, std::string
> name_map
;
1223 expand_genblock(std::string(), str
+ ".", name_map
);
1226 for (size_t i
= 0; i
< children
.size(); i
++) {
1227 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1228 current_ast_mod
->children
.push_back(children
[i
]);
1232 did_something
= true;
1235 // simplify generate-if blocks
1236 if (type
== AST_GENIF
&& children
.size() != 0)
1238 AstNode
*buf
= children
[0]->clone();
1239 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1240 if (buf
->type
!= AST_CONSTANT
) {
1241 // for (auto f : log_files)
1242 // dumpAst(f, "verilog-ast> ");
1243 log_file_error(filename
, linenum
, "Condition for generate if is not constant!\n");
1245 if (buf
->asBool() != 0) {
1247 buf
= children
[1]->clone();
1250 buf
= children
.size() > 2 ? children
[2]->clone() : NULL
;
1255 if (buf
->type
!= AST_GENBLOCK
)
1256 buf
= new AstNode(AST_GENBLOCK
, buf
);
1258 if (!buf
->str
.empty()) {
1259 std::map
<std::string
, std::string
> name_map
;
1260 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1263 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1264 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1265 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1268 buf
->children
.clear();
1273 did_something
= true;
1276 // simplify generate-case blocks
1277 if (type
== AST_GENCASE
&& children
.size() != 0)
1279 AstNode
*buf
= children
[0]->clone();
1280 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1281 if (buf
->type
!= AST_CONSTANT
) {
1282 // for (auto f : log_files)
1283 // dumpAst(f, "verilog-ast> ");
1284 log_file_error(filename
, linenum
, "Condition for generate case is not constant!\n");
1287 bool ref_signed
= buf
->is_signed
;
1288 RTLIL::Const ref_value
= buf
->bitsAsConst();
1291 AstNode
*selected_case
= NULL
;
1292 for (size_t i
= 1; i
< children
.size(); i
++)
1294 log_assert(children
.at(i
)->type
== AST_COND
|| children
.at(i
)->type
== AST_CONDX
|| children
.at(i
)->type
== AST_CONDZ
);
1296 AstNode
*this_genblock
= NULL
;
1297 for (auto child
: children
.at(i
)->children
) {
1298 log_assert(this_genblock
== NULL
);
1299 if (child
->type
== AST_GENBLOCK
)
1300 this_genblock
= child
;
1303 for (auto child
: children
.at(i
)->children
)
1305 if (child
->type
== AST_DEFAULT
) {
1306 if (selected_case
== NULL
)
1307 selected_case
= this_genblock
;
1310 if (child
->type
== AST_GENBLOCK
)
1313 buf
= child
->clone();
1314 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1315 if (buf
->type
!= AST_CONSTANT
) {
1316 // for (auto f : log_files)
1317 // dumpAst(f, "verilog-ast> ");
1318 log_file_error(filename
, linenum
, "Expression in generate case is not constant!\n");
1321 bool is_selected
= RTLIL::const_eq(ref_value
, buf
->bitsAsConst(), ref_signed
&& buf
->is_signed
, ref_signed
&& buf
->is_signed
, 1).as_bool();
1325 selected_case
= this_genblock
;
1326 i
= children
.size();
1332 if (selected_case
!= NULL
)
1334 log_assert(selected_case
->type
== AST_GENBLOCK
);
1335 buf
= selected_case
->clone();
1337 if (!buf
->str
.empty()) {
1338 std::map
<std::string
, std::string
> name_map
;
1339 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1342 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1343 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1344 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1347 buf
->children
.clear();
1352 did_something
= true;
1355 // unroll cell arrays
1356 if (type
== AST_CELLARRAY
)
1358 if (!children
.at(0)->range_valid
)
1359 log_file_error(filename
, linenum
, "Non-constant array range on cell array.\n");
1361 newNode
= new AstNode(AST_GENBLOCK
);
1362 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;
1364 for (int i
= 0; i
< num
; i
++) {
1365 int idx
= children
.at(0)->range_left
> children
.at(0)->range_right
? children
.at(0)->range_right
+ i
: children
.at(0)->range_right
- i
;
1366 AstNode
*new_cell
= children
.at(1)->clone();
1367 newNode
->children
.push_back(new_cell
);
1368 new_cell
->str
+= stringf("[%d]", idx
);
1369 if (new_cell
->type
== AST_PRIMITIVE
) {
1370 log_file_error(filename
, linenum
, "Cell arrays of primitives are currently not supported.\n");
1372 log_assert(new_cell
->children
.at(0)->type
== AST_CELLTYPE
);
1373 new_cell
->children
.at(0)->str
= stringf("$array:%d:%d:%s", i
, num
, new_cell
->children
.at(0)->str
.c_str());
1380 // replace primitives with assignments
1381 if (type
== AST_PRIMITIVE
)
1383 if (children
.size() < 2)
1384 log_file_error(filename
, linenum
, "Insufficient number of arguments for primitive `%s'!\n", str
.c_str());
1386 std::vector
<AstNode
*> children_list
;
1387 for (auto child
: children
) {
1388 log_assert(child
->type
== AST_ARGUMENT
);
1389 log_assert(child
->children
.size() == 1);
1390 children_list
.push_back(child
->children
[0]);
1391 child
->children
.clear();
1396 if (str
== "bufif0" || str
== "bufif1" || str
== "notif0" || str
== "notif1")
1398 if (children_list
.size() != 3)
1399 log_file_error(filename
, linenum
, "Invalid number of arguments for primitive `%s'!\n", str
.c_str());
1401 std::vector
<RTLIL::State
> z_const(1, RTLIL::State::Sz
);
1403 AstNode
*mux_input
= children_list
.at(1);
1404 if (str
== "notif0" || str
== "notif1") {
1405 mux_input
= new AstNode(AST_BIT_NOT
, mux_input
);
1407 AstNode
*node
= new AstNode(AST_TERNARY
, children_list
.at(2));
1408 if (str
== "bufif0") {
1409 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1410 node
->children
.push_back(mux_input
);
1412 node
->children
.push_back(mux_input
);
1413 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1418 children
.push_back(children_list
.at(0));
1419 children
.back()->was_checked
= true;
1420 children
.push_back(node
);
1421 did_something
= true;
1425 AstNodeType op_type
= AST_NONE
;
1426 bool invert_results
= false;
1429 op_type
= AST_BIT_AND
;
1431 op_type
= AST_BIT_AND
, invert_results
= true;
1433 op_type
= AST_BIT_OR
;
1435 op_type
= AST_BIT_OR
, invert_results
= true;
1437 op_type
= AST_BIT_XOR
;
1439 op_type
= AST_BIT_XOR
, invert_results
= true;
1443 op_type
= AST_POS
, invert_results
= true;
1444 log_assert(op_type
!= AST_NONE
);
1446 AstNode
*node
= children_list
[1];
1447 if (op_type
!= AST_POS
)
1448 for (size_t i
= 2; i
< children_list
.size(); i
++)
1449 node
= new AstNode(op_type
, node
, children_list
[i
]);
1451 node
= new AstNode(AST_BIT_NOT
, node
);
1455 children
.push_back(children_list
[0]);
1456 children
.back()->was_checked
= true;
1457 children
.push_back(node
);
1458 did_something
= true;
1462 // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
1463 // a big case block that selects the correct single-bit assignment.
1464 if (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) {
1465 if (children
[0]->type
!= AST_IDENTIFIER
|| children
[0]->children
.size() == 0)
1466 goto skip_dynamic_range_lvalue_expansion
;
1467 if (children
[0]->children
[0]->range_valid
|| did_something
)
1468 goto skip_dynamic_range_lvalue_expansion
;
1469 if (children
[0]->id2ast
== NULL
|| children
[0]->id2ast
->type
!= AST_WIRE
)
1470 goto skip_dynamic_range_lvalue_expansion
;
1471 if (!children
[0]->id2ast
->range_valid
)
1472 goto skip_dynamic_range_lvalue_expansion
;
1473 int source_width
= children
[0]->id2ast
->range_left
- children
[0]->id2ast
->range_right
+ 1;
1474 int result_width
= 1;
1475 AstNode
*shift_expr
= NULL
;
1476 AstNode
*range
= children
[0]->children
[0];
1477 if (range
->children
.size() == 1) {
1478 shift_expr
= range
->children
[0]->clone();
1480 shift_expr
= range
->children
[1]->clone();
1481 AstNode
*left_at_zero_ast
= range
->children
[0]->clone();
1482 AstNode
*right_at_zero_ast
= range
->children
[1]->clone();
1483 while (left_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1484 while (right_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1485 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
1486 log_file_error(filename
, linenum
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
1487 result_width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
1489 did_something
= true;
1490 newNode
= new AstNode(AST_CASE
, shift_expr
);
1491 for (int i
= 0; i
<= source_width
-result_width
; i
++) {
1492 int start_bit
= children
[0]->id2ast
->range_right
+ i
;
1493 AstNode
*cond
= new AstNode(AST_COND
, mkconst_int(start_bit
, true));
1494 AstNode
*lvalue
= children
[0]->clone();
1495 lvalue
->delete_children();
1496 lvalue
->children
.push_back(new AstNode(AST_RANGE
,
1497 mkconst_int(start_bit
+result_width
-1, true), mkconst_int(start_bit
, true)));
1498 cond
->children
.push_back(new AstNode(AST_BLOCK
, new AstNode(type
, lvalue
, children
[1]->clone())));
1499 newNode
->children
.push_back(cond
);
1503 skip_dynamic_range_lvalue_expansion
:;
1505 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && current_block
!= NULL
)
1507 std::stringstream sstr
;
1508 sstr
<< "$formal$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1509 std::string id_check
= sstr
.str() + "_CHECK", id_en
= sstr
.str() + "_EN";
1511 AstNode
*wire_check
= new AstNode(AST_WIRE
);
1512 wire_check
->str
= id_check
;
1513 wire_check
->was_checked
= true;
1514 current_ast_mod
->children
.push_back(wire_check
);
1515 current_scope
[wire_check
->str
] = wire_check
;
1516 while (wire_check
->simplify(true, false, false, 1, -1, false, false)) { }
1518 AstNode
*wire_en
= new AstNode(AST_WIRE
);
1519 wire_en
->str
= id_en
;
1520 wire_en
->was_checked
= true;
1521 current_ast_mod
->children
.push_back(wire_en
);
1522 if (current_always_clocked
) {
1523 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)))));
1524 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->str
= id_en
;
1525 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->was_checked
= true;
1527 current_scope
[wire_en
->str
] = wire_en
;
1528 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
1530 std::vector
<RTLIL::State
> x_bit
;
1531 x_bit
.push_back(RTLIL::State::Sx
);
1533 AstNode
*assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bit
, false));
1534 assign_check
->children
[0]->str
= id_check
;
1535 assign_check
->children
[0]->was_checked
= true;
1537 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, 1));
1538 assign_en
->children
[0]->str
= id_en
;
1539 assign_en
->children
[0]->was_checked
= true;
1541 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
1542 default_signals
->children
.push_back(assign_check
);
1543 default_signals
->children
.push_back(assign_en
);
1544 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
1546 assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_REDUCE_BOOL
, children
[0]->clone()));
1547 assign_check
->children
[0]->str
= id_check
;
1548 assign_check
->children
[0]->was_checked
= true;
1550 if (current_always
== nullptr || current_always
->type
!= AST_INITIAL
) {
1551 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(1, false, 1));
1553 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_FCALL
));
1554 assign_en
->children
[1]->str
= "\\$initstate";
1556 assign_en
->children
[0]->str
= id_en
;
1557 assign_en
->children
[0]->was_checked
= true;
1559 newNode
= new AstNode(AST_BLOCK
);
1560 newNode
->children
.push_back(assign_check
);
1561 newNode
->children
.push_back(assign_en
);
1563 AstNode
*assertnode
= new AstNode(type
);
1564 assertnode
->str
= str
;
1565 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1566 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1567 assertnode
->children
[0]->str
= id_check
;
1568 assertnode
->children
[1]->str
= id_en
;
1569 assertnode
->attributes
.swap(attributes
);
1570 current_ast_mod
->children
.push_back(assertnode
);
1575 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && children
.size() == 1)
1577 children
.push_back(mkconst_int(1, false, 1));
1578 did_something
= true;
1581 // found right-hand side identifier for memory -> replace with memory read port
1582 if (stage
> 1 && type
== AST_IDENTIFIER
&& id2ast
!= NULL
&& id2ast
->type
== AST_MEMORY
&& !in_lvalue
&&
1583 children
.size() == 1 && children
[0]->type
== AST_RANGE
&& children
[0]->children
.size() == 1) {
1584 newNode
= new AstNode(AST_MEMRD
, children
[0]->children
[0]->clone());
1586 newNode
->id2ast
= id2ast
;
1590 // assignment with nontrivial member in left-hand concat expression -> split assignment
1591 if ((type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_CONCAT
&& width_hint
> 0)
1593 bool found_nontrivial_member
= false;
1595 for (auto child
: children
[0]->children
) {
1596 if (child
->type
== AST_IDENTIFIER
&& child
->id2ast
!= NULL
&& child
->id2ast
->type
== AST_MEMORY
)
1597 found_nontrivial_member
= true;
1600 if (found_nontrivial_member
)
1602 newNode
= new AstNode(AST_BLOCK
);
1604 AstNode
*wire_tmp
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
1605 wire_tmp
->str
= stringf("$splitcmplxassign$%s:%d$%d", filename
.c_str(), linenum
, autoidx
++);
1606 current_ast_mod
->children
.push_back(wire_tmp
);
1607 current_scope
[wire_tmp
->str
] = wire_tmp
;
1608 wire_tmp
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
1609 while (wire_tmp
->simplify(true, false, false, 1, -1, false, false)) { }
1610 wire_tmp
->is_logic
= true;
1612 AstNode
*wire_tmp_id
= new AstNode(AST_IDENTIFIER
);
1613 wire_tmp_id
->str
= wire_tmp
->str
;
1615 newNode
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, wire_tmp_id
, children
[1]->clone()));
1616 newNode
->children
.back()->was_checked
= true;
1619 for (auto child
: children
[0]->children
)
1621 int child_width_hint
= -1;
1622 bool child_sign_hint
= true;
1623 child
->detectSignWidth(child_width_hint
, child_sign_hint
);
1625 AstNode
*rhs
= wire_tmp_id
->clone();
1626 rhs
->children
.push_back(new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+child_width_hint
-1, true), AstNode::mkconst_int(cursor
, true)));
1627 newNode
->children
.push_back(new AstNode(type
, child
->clone(), rhs
));
1629 cursor
+= child_width_hint
;
1636 // assignment with memory in left-hand side expression -> replace with memory write port
1637 if (stage
> 1 && (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_IDENTIFIER
&&
1638 children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
&& children
[0]->id2ast
->children
.size() >= 2 &&
1639 children
[0]->id2ast
->children
[0]->range_valid
&& children
[0]->id2ast
->children
[1]->range_valid
&&
1640 (children
[0]->children
.size() == 1 || children
[0]->children
.size() == 2) && children
[0]->children
[0]->type
== AST_RANGE
)
1642 std::stringstream sstr
;
1643 sstr
<< "$memwr$" << children
[0]->str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1644 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA", id_en
= sstr
.str() + "_EN";
1646 int mem_width
, mem_size
, addr_bits
;
1647 bool mem_signed
= children
[0]->id2ast
->is_signed
;
1648 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
1650 int data_range_left
= children
[0]->id2ast
->children
[0]->range_left
;
1651 int data_range_right
= children
[0]->id2ast
->children
[0]->range_right
;
1652 int mem_data_range_offset
= std::min(data_range_left
, data_range_right
);
1654 int addr_width_hint
= -1;
1655 bool addr_sign_hint
= true;
1656 children
[0]->children
[0]->children
[0]->detectSignWidthWorker(addr_width_hint
, addr_sign_hint
);
1657 addr_bits
= std::max(addr_bits
, addr_width_hint
);
1659 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
1660 wire_addr
->str
= id_addr
;
1661 wire_addr
->was_checked
= true;
1662 current_ast_mod
->children
.push_back(wire_addr
);
1663 current_scope
[wire_addr
->str
] = wire_addr
;
1664 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
1666 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
1667 wire_data
->str
= id_data
;
1668 wire_data
->was_checked
= true;
1669 wire_data
->is_signed
= mem_signed
;
1670 current_ast_mod
->children
.push_back(wire_data
);
1671 current_scope
[wire_data
->str
] = wire_data
;
1672 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
1674 AstNode
*wire_en
= nullptr;
1675 if (current_always
->type
!= AST_INITIAL
) {
1676 wire_en
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
1677 wire_en
->str
= id_en
;
1678 wire_en
->was_checked
= true;
1679 current_ast_mod
->children
.push_back(wire_en
);
1680 current_scope
[wire_en
->str
] = wire_en
;
1681 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
1684 std::vector
<RTLIL::State
> x_bits_addr
, x_bits_data
, set_bits_en
;
1685 for (int i
= 0; i
< addr_bits
; i
++)
1686 x_bits_addr
.push_back(RTLIL::State::Sx
);
1687 for (int i
= 0; i
< mem_width
; i
++)
1688 x_bits_data
.push_back(RTLIL::State::Sx
);
1689 for (int i
= 0; i
< mem_width
; i
++)
1690 set_bits_en
.push_back(RTLIL::State::S1
);
1692 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_addr
, false));
1693 assign_addr
->children
[0]->str
= id_addr
;
1694 assign_addr
->children
[0]->was_checked
= true;
1696 AstNode
*assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_data
, false));
1697 assign_data
->children
[0]->str
= id_data
;
1698 assign_data
->children
[0]->was_checked
= true;
1700 AstNode
*assign_en
= nullptr;
1701 if (current_always
->type
!= AST_INITIAL
) {
1702 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, mem_width
));
1703 assign_en
->children
[0]->str
= id_en
;
1704 assign_en
->children
[0]->was_checked
= true;
1707 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
1708 default_signals
->children
.push_back(assign_addr
);
1709 default_signals
->children
.push_back(assign_data
);
1710 if (current_always
->type
!= AST_INITIAL
)
1711 default_signals
->children
.push_back(assign_en
);
1712 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
1714 assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
1715 assign_addr
->children
[0]->str
= id_addr
;
1716 assign_addr
->children
[0]->was_checked
= true;
1718 if (children
[0]->children
.size() == 2)
1720 if (children
[0]->children
[1]->range_valid
)
1722 int offset
= children
[0]->children
[1]->range_right
;
1723 int width
= children
[0]->children
[1]->range_left
- offset
+ 1;
1724 offset
-= mem_data_range_offset
;
1726 std::vector
<RTLIL::State
> padding_x(offset
, RTLIL::State::Sx
);
1728 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1729 new AstNode(AST_CONCAT
, mkconst_bits(padding_x
, false), children
[1]->clone()));
1730 assign_data
->children
[0]->str
= id_data
;
1731 assign_data
->children
[0]->was_checked
= true;
1733 if (current_always
->type
!= AST_INITIAL
) {
1734 for (int i
= 0; i
< mem_width
; i
++)
1735 set_bits_en
[i
] = offset
<= i
&& i
< offset
+width
? RTLIL::State::S1
: RTLIL::State::S0
;
1736 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
1737 assign_en
->children
[0]->str
= id_en
;
1738 assign_en
->children
[0]->was_checked
= true;
1743 AstNode
*the_range
= children
[0]->children
[1];
1744 AstNode
*left_at_zero_ast
= the_range
->children
[0]->clone();
1745 AstNode
*right_at_zero_ast
= the_range
->children
.size() >= 2 ? the_range
->children
[1]->clone() : left_at_zero_ast
->clone();
1746 AstNode
*offset_ast
= right_at_zero_ast
->clone();
1748 if (mem_data_range_offset
)
1749 offset_ast
= new AstNode(AST_SUB
, offset_ast
, mkconst_int(mem_data_range_offset
, true));
1751 while (left_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
1752 while (right_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
1753 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
1754 log_file_error(filename
, linenum
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
1755 int width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
1757 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1758 new AstNode(AST_SHIFT_LEFT
, children
[1]->clone(), offset_ast
->clone()));
1759 assign_data
->children
[0]->str
= id_data
;
1760 assign_data
->children
[0]->was_checked
= true;
1762 if (current_always
->type
!= AST_INITIAL
) {
1763 for (int i
= 0; i
< mem_width
; i
++)
1764 set_bits_en
[i
] = i
< width
? RTLIL::State::S1
: RTLIL::State::S0
;
1765 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1766 new AstNode(AST_SHIFT_LEFT
, mkconst_bits(set_bits_en
, false), offset_ast
->clone()));
1767 assign_en
->children
[0]->str
= id_en
;
1768 assign_en
->children
[0]->was_checked
= true;
1771 delete left_at_zero_ast
;
1772 delete right_at_zero_ast
;
1778 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[1]->clone());
1779 assign_data
->children
[0]->str
= id_data
;
1780 assign_data
->children
[0]->was_checked
= true;
1782 if (current_always
->type
!= AST_INITIAL
) {
1783 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
1784 assign_en
->children
[0]->str
= id_en
;
1785 assign_en
->children
[0]->was_checked
= true;
1789 newNode
= new AstNode(AST_BLOCK
);
1790 newNode
->children
.push_back(assign_addr
);
1791 newNode
->children
.push_back(assign_data
);
1792 if (current_always
->type
!= AST_INITIAL
)
1793 newNode
->children
.push_back(assign_en
);
1795 AstNode
*wrnode
= new AstNode(current_always
->type
== AST_INITIAL
? AST_MEMINIT
: AST_MEMWR
);
1796 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1797 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1798 if (current_always
->type
!= AST_INITIAL
)
1799 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1801 wrnode
->children
.push_back(AstNode::mkconst_int(1, false));
1802 wrnode
->str
= children
[0]->str
;
1803 wrnode
->id2ast
= children
[0]->id2ast
;
1804 wrnode
->children
[0]->str
= id_addr
;
1805 wrnode
->children
[1]->str
= id_data
;
1806 if (current_always
->type
!= AST_INITIAL
)
1807 wrnode
->children
[2]->str
= id_en
;
1808 current_ast_mod
->children
.push_back(wrnode
);
1813 // replace function and task calls with the code from the function or task
1814 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && !str
.empty())
1816 if (type
== AST_FCALL
)
1818 if (str
== "\\$initstate")
1820 int myidx
= autoidx
++;
1822 AstNode
*wire
= new AstNode(AST_WIRE
);
1823 wire
->str
= stringf("$initstate$%d_wire", myidx
);
1824 current_ast_mod
->children
.push_back(wire
);
1825 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
1827 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
), new AstNode(AST_ARGUMENT
, new AstNode(AST_IDENTIFIER
)));
1828 cell
->str
= stringf("$initstate$%d", myidx
);
1829 cell
->children
[0]->str
= "$initstate";
1830 cell
->children
[1]->str
= "\\Y";
1831 cell
->children
[1]->children
[0]->str
= wire
->str
;
1832 cell
->children
[1]->children
[0]->id2ast
= wire
;
1833 current_ast_mod
->children
.push_back(cell
);
1834 while (cell
->simplify(true, false, false, 1, -1, false, false)) { }
1836 newNode
= new AstNode(AST_IDENTIFIER
);
1837 newNode
->str
= wire
->str
;
1838 newNode
->id2ast
= wire
;
1842 if (str
== "\\$past")
1845 goto replace_fcall_later
;
1849 if (GetSize(children
) != 1 && GetSize(children
) != 2)
1850 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1 or 2.\n",
1851 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
1853 if (!current_always_clocked
)
1854 log_file_error(filename
, linenum
, "System function %s is only allowed in clocked blocks.\n",
1855 RTLIL::unescape_id(str
).c_str());
1857 if (GetSize(children
) == 2)
1859 AstNode
*buf
= children
[1]->clone();
1860 while (buf
->simplify(true, false, false, stage
, -1, false, false)) { }
1861 if (buf
->type
!= AST_CONSTANT
)
1862 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
1864 num_steps
= buf
->asInt(true);
1868 AstNode
*block
= nullptr;
1870 for (auto child
: current_always
->children
)
1871 if (child
->type
== AST_BLOCK
)
1874 log_assert(block
!= nullptr);
1876 if (num_steps
== 0) {
1877 newNode
= children
[0]->clone();
1881 int myidx
= autoidx
++;
1882 AstNode
*outreg
= nullptr;
1884 for (int i
= 0; i
< num_steps
; i
++)
1886 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
1887 mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
1889 reg
->str
= stringf("$past$%s:%d$%d$%d", filename
.c_str(), linenum
, myidx
, i
);
1892 current_ast_mod
->children
.push_back(reg
);
1894 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
1896 AstNode
*regid
= new AstNode(AST_IDENTIFIER
);
1897 regid
->str
= reg
->str
;
1898 regid
->id2ast
= reg
;
1899 regid
->was_checked
= true;
1901 AstNode
*rhs
= nullptr;
1903 if (outreg
== nullptr) {
1904 rhs
= children
.at(0)->clone();
1906 rhs
= new AstNode(AST_IDENTIFIER
);
1907 rhs
->str
= outreg
->str
;
1908 rhs
->id2ast
= outreg
;
1911 block
->children
.push_back(new AstNode(AST_ASSIGN_LE
, regid
, rhs
));
1915 newNode
= new AstNode(AST_IDENTIFIER
);
1916 newNode
->str
= outreg
->str
;
1917 newNode
->id2ast
= outreg
;
1921 if (str
== "\\$stable" || str
== "\\$rose" || str
== "\\$fell" || str
== "\\$changed")
1923 if (GetSize(children
) != 1)
1924 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1.\n",
1925 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
1927 if (!current_always_clocked
)
1928 log_file_error(filename
, linenum
, "System function %s is only allowed in clocked blocks.\n",
1929 RTLIL::unescape_id(str
).c_str());
1931 AstNode
*present
= children
.at(0)->clone();
1932 AstNode
*past
= clone();
1933 past
->str
= "\\$past";
1935 if (str
== "\\$stable")
1936 newNode
= new AstNode(AST_EQ
, past
, present
);
1938 else if (str
== "\\$changed")
1939 newNode
= new AstNode(AST_NE
, past
, present
);
1941 else if (str
== "\\$rose")
1942 newNode
= new AstNode(AST_LOGIC_AND
,
1943 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false))),
1944 new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false)));
1946 else if (str
== "\\$fell")
1947 newNode
= new AstNode(AST_LOGIC_AND
,
1948 new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false)),
1949 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false))));
1957 // $anyconst and $anyseq are mapped in AstNode::genRTLIL()
1958 if (str
== "\\$anyconst" || str
== "\\$anyseq" || str
== "\\$allconst" || str
== "\\$allseq") {
1959 recursion_counter
--;
1963 if (str
== "\\$clog2")
1965 if (children
.size() != 1)
1966 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1.\n",
1967 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
1969 AstNode
*buf
= children
[0]->clone();
1970 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1971 if (buf
->type
!= AST_CONSTANT
)
1972 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
1974 RTLIL::Const arg_value
= buf
->bitsAsConst();
1975 if (arg_value
.as_bool())
1976 arg_value
= const_sub(arg_value
, 1, false, false, GetSize(arg_value
));
1979 uint32_t result
= 0;
1980 for (size_t i
= 0; i
< arg_value
.bits
.size(); i
++)
1981 if (arg_value
.bits
.at(i
) == RTLIL::State::S1
)
1984 newNode
= mkconst_int(result
, true);
1988 if (str
== "\\$size" || str
== "\\$bits")
1990 if (str
== "\\$bits" && children
.size() != 1)
1991 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1.\n",
1992 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
1994 if (str
== "\\$size" && children
.size() != 1 && children
.size() != 2)
1995 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1 or 2.\n",
1996 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
1999 if (str
== "\\$size" && children
.size() == 2) {
2000 AstNode
*buf
= children
[1]->clone();
2001 // Evaluate constant expression
2002 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2003 dim
= buf
->asInt(false);
2006 AstNode
*buf
= children
[0]->clone();
2008 AstNode
*id_ast
= NULL
;
2011 //while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2012 buf
->detectSignWidth(width_hint
, sign_hint
);
2014 if (buf
->type
== AST_IDENTIFIER
) {
2015 id_ast
= buf
->id2ast
;
2016 if (id_ast
== NULL
&& current_scope
.count(buf
->str
))
2017 id_ast
= current_scope
.at(buf
->str
);
2019 log_file_error(filename
, linenum
, "Failed to resolve identifier %s for width detection!\n", buf
->str
.c_str());
2020 if (id_ast
->type
== AST_MEMORY
) {
2021 // We got here only if the argument is a memory
2022 // Otherwise $size() and $bits() return the expression width
2023 AstNode
*mem_range
= id_ast
->children
[1];
2024 if (str
== "\\$bits") {
2025 if (mem_range
->type
== AST_RANGE
) {
2026 if (!mem_range
->range_valid
)
2027 log_file_error(filename
, linenum
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2028 mem_depth
= mem_range
->range_left
- mem_range
->range_right
+ 1;
2030 log_file_error(filename
, linenum
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2033 if (mem_range
->type
== AST_RANGE
) {
2034 if (!mem_range
->range_valid
)
2035 log_file_error(filename
, linenum
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2037 if (id_ast
->multirange_dimensions
.empty())
2040 dims
= GetSize(id_ast
->multirange_dimensions
)/2;
2042 width_hint
= (dims
> 1) ? id_ast
->multirange_dimensions
[1] : (mem_range
->range_left
- mem_range
->range_right
+ 1);
2043 else if (dim
<= dims
) {
2044 width_hint
= id_ast
->multirange_dimensions
[2*dim
-1];
2045 } else if ((dim
> dims
+1) || (dim
< 0))
2046 log_file_error(filename
, linenum
, "Dimension %d out of range in `%s', as it only has dimensions 1..%d!\n", dim
, buf
->str
.c_str(), dims
+1);
2048 log_file_error(filename
, linenum
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2054 newNode
= mkconst_int(width_hint
* mem_depth
, false);
2058 if (str
== "\\$ln" || str
== "\\$log10" || str
== "\\$exp" || str
== "\\$sqrt" || str
== "\\$pow" ||
2059 str
== "\\$floor" || str
== "\\$ceil" || str
== "\\$sin" || str
== "\\$cos" || str
== "\\$tan" ||
2060 str
== "\\$asin" || str
== "\\$acos" || str
== "\\$atan" || str
== "\\$atan2" || str
== "\\$hypot" ||
2061 str
== "\\$sinh" || str
== "\\$cosh" || str
== "\\$tanh" || str
== "\\$asinh" || str
== "\\$acosh" || str
== "\\$atanh" ||
2062 str
== "\\$rtoi" || str
== "\\$itor")
2064 bool func_with_two_arguments
= str
== "\\$pow" || str
== "\\$atan2" || str
== "\\$hypot";
2065 double x
= 0, y
= 0;
2067 if (func_with_two_arguments
) {
2068 if (children
.size() != 2)
2069 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 2.\n",
2070 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2072 if (children
.size() != 1)
2073 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1.\n",
2074 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2077 if (children
.size() >= 1) {
2078 while (children
[0]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2079 if (!children
[0]->isConst())
2080 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant argument.\n",
2081 RTLIL::unescape_id(str
).c_str());
2082 int child_width_hint
= width_hint
;
2083 bool child_sign_hint
= sign_hint
;
2084 children
[0]->detectSignWidth(child_width_hint
, child_sign_hint
);
2085 x
= children
[0]->asReal(child_sign_hint
);
2088 if (children
.size() >= 2) {
2089 while (children
[1]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2090 if (!children
[1]->isConst())
2091 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant argument.\n",
2092 RTLIL::unescape_id(str
).c_str());
2093 int child_width_hint
= width_hint
;
2094 bool child_sign_hint
= sign_hint
;
2095 children
[1]->detectSignWidth(child_width_hint
, child_sign_hint
);
2096 y
= children
[1]->asReal(child_sign_hint
);
2099 if (str
== "\\$rtoi") {
2100 newNode
= AstNode::mkconst_int(x
, true);
2102 newNode
= new AstNode(AST_REALVALUE
);
2103 if (str
== "\\$ln") newNode
->realvalue
= ::log(x
);
2104 else if (str
== "\\$log10") newNode
->realvalue
= ::log10(x
);
2105 else if (str
== "\\$exp") newNode
->realvalue
= ::exp(x
);
2106 else if (str
== "\\$sqrt") newNode
->realvalue
= ::sqrt(x
);
2107 else if (str
== "\\$pow") newNode
->realvalue
= ::pow(x
, y
);
2108 else if (str
== "\\$floor") newNode
->realvalue
= ::floor(x
);
2109 else if (str
== "\\$ceil") newNode
->realvalue
= ::ceil(x
);
2110 else if (str
== "\\$sin") newNode
->realvalue
= ::sin(x
);
2111 else if (str
== "\\$cos") newNode
->realvalue
= ::cos(x
);
2112 else if (str
== "\\$tan") newNode
->realvalue
= ::tan(x
);
2113 else if (str
== "\\$asin") newNode
->realvalue
= ::asin(x
);
2114 else if (str
== "\\$acos") newNode
->realvalue
= ::acos(x
);
2115 else if (str
== "\\$atan") newNode
->realvalue
= ::atan(x
);
2116 else if (str
== "\\$atan2") newNode
->realvalue
= ::atan2(x
, y
);
2117 else if (str
== "\\$hypot") newNode
->realvalue
= ::hypot(x
, y
);
2118 else if (str
== "\\$sinh") newNode
->realvalue
= ::sinh(x
);
2119 else if (str
== "\\$cosh") newNode
->realvalue
= ::cosh(x
);
2120 else if (str
== "\\$tanh") newNode
->realvalue
= ::tanh(x
);
2121 else if (str
== "\\$asinh") newNode
->realvalue
= ::asinh(x
);
2122 else if (str
== "\\$acosh") newNode
->realvalue
= ::acosh(x
);
2123 else if (str
== "\\$atanh") newNode
->realvalue
= ::atanh(x
);
2124 else if (str
== "\\$itor") newNode
->realvalue
= x
;
2130 if (current_scope
.count(str
) != 0 && current_scope
[str
]->type
== AST_DPI_FUNCTION
)
2132 AstNode
*dpi_decl
= current_scope
[str
];
2134 std::string rtype
, fname
;
2135 std::vector
<std::string
> argtypes
;
2136 std::vector
<AstNode
*> args
;
2138 rtype
= RTLIL::unescape_id(dpi_decl
->children
.at(0)->str
);
2139 fname
= RTLIL::unescape_id(dpi_decl
->children
.at(1)->str
);
2141 for (int i
= 2; i
< GetSize(dpi_decl
->children
); i
++)
2143 if (i
-2 >= GetSize(children
))
2144 log_file_error(filename
, linenum
, "Insufficient number of arguments in DPI function call.\n");
2146 argtypes
.push_back(RTLIL::unescape_id(dpi_decl
->children
.at(i
)->str
));
2147 args
.push_back(children
.at(i
-2)->clone());
2148 while (args
.back()->simplify(true, false, false, stage
, -1, false, true)) { }
2150 if (args
.back()->type
!= AST_CONSTANT
&& args
.back()->type
!= AST_REALVALUE
)
2151 log_file_error(filename
, linenum
, "Failed to evaluate DPI function with non-constant argument.\n");
2154 newNode
= dpi_call(rtype
, fname
, argtypes
, args
);
2156 for (auto arg
: args
)
2162 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_FUNCTION
)
2163 log_file_error(filename
, linenum
, "Can't resolve function name `%s'.\n", str
.c_str());
2166 if (type
== AST_TCALL
)
2168 if (str
== "$finish" || str
== "$stop")
2170 if (!current_always
|| current_always
->type
!= AST_INITIAL
)
2171 log_file_error(filename
, linenum
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
2173 log_file_error(filename
, linenum
, "System task `%s' executed.\n", str
.c_str());
2176 if (str
== "\\$readmemh" || str
== "\\$readmemb")
2178 if (GetSize(children
) < 2 || GetSize(children
) > 4)
2179 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 2-4.\n",
2180 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2182 AstNode
*node_filename
= children
[0]->clone();
2183 while (node_filename
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2184 if (node_filename
->type
!= AST_CONSTANT
)
2185 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
2187 AstNode
*node_memory
= children
[1]->clone();
2188 while (node_memory
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2189 if (node_memory
->type
!= AST_IDENTIFIER
|| node_memory
->id2ast
== nullptr || node_memory
->id2ast
->type
!= AST_MEMORY
)
2190 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str
.c_str());
2192 int start_addr
= -1, finish_addr
= -1;
2194 if (GetSize(children
) > 2) {
2195 AstNode
*node_addr
= children
[2]->clone();
2196 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2197 if (node_addr
->type
!= AST_CONSTANT
)
2198 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str
.c_str());
2199 start_addr
= int(node_addr
->asInt(false));
2202 if (GetSize(children
) > 3) {
2203 AstNode
*node_addr
= children
[3]->clone();
2204 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2205 if (node_addr
->type
!= AST_CONSTANT
)
2206 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str
.c_str());
2207 finish_addr
= int(node_addr
->asInt(false));
2210 bool unconditional_init
= false;
2211 if (current_always
->type
== AST_INITIAL
) {
2212 pool
<AstNode
*> queue
;
2213 log_assert(current_always
->children
[0]->type
== AST_BLOCK
);
2214 queue
.insert(current_always
->children
[0]);
2215 while (!unconditional_init
&& !queue
.empty()) {
2216 pool
<AstNode
*> next_queue
;
2217 for (auto n
: queue
)
2218 for (auto c
: n
->children
) {
2220 unconditional_init
= true;
2221 next_queue
.insert(c
);
2223 next_queue
.swap(queue
);
2227 newNode
= readmem(str
== "\\$readmemh", node_filename
->bitsAsConst().decode_string(), node_memory
->id2ast
, start_addr
, finish_addr
, unconditional_init
);
2228 delete node_filename
;
2233 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_TASK
)
2234 log_file_error(filename
, linenum
, "Can't resolve task name `%s'.\n", str
.c_str());
2237 AstNode
*decl
= current_scope
[str
];
2239 std::stringstream sstr
;
2240 sstr
<< "$func$" << str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++) << "$";
2241 std::string prefix
= sstr
.str();
2243 bool recommend_const_eval
= false;
2244 bool require_const_eval
= in_param
? false : has_const_only_constructs(recommend_const_eval
);
2245 if ((in_param
|| recommend_const_eval
|| require_const_eval
) && !decl
->attributes
.count("\\via_celltype"))
2247 bool all_args_const
= true;
2248 for (auto child
: children
) {
2249 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
2250 if (child
->type
!= AST_CONSTANT
)
2251 all_args_const
= false;
2254 if (all_args_const
) {
2255 AstNode
*func_workspace
= current_scope
[str
]->clone();
2256 newNode
= func_workspace
->eval_const_function(this);
2257 delete func_workspace
;
2262 log_file_error(filename
, linenum
, "Non-constant function call in constant expression.\n");
2263 if (require_const_eval
)
2264 log_file_error(filename
, linenum
, "Function %s can only be called with constant arguments.\n", str
.c_str());
2267 size_t arg_count
= 0;
2268 std::map
<std::string
, std::string
> replace_rules
;
2269 vector
<AstNode
*> added_mod_children
;
2270 dict
<std::string
, AstNode
*> wire_cache
;
2271 vector
<AstNode
*> new_stmts
;
2272 vector
<AstNode
*> output_assignments
;
2274 if (current_block
== NULL
)
2276 log_assert(type
== AST_FCALL
);
2278 AstNode
*wire
= NULL
;
2279 for (auto child
: decl
->children
)
2280 if (child
->type
== AST_WIRE
&& child
->str
== str
)
2281 wire
= child
->clone();
2282 log_assert(wire
!= NULL
);
2284 wire
->str
= prefix
+ str
;
2286 wire
->is_input
= false;
2287 wire
->is_output
= false;
2289 current_ast_mod
->children
.push_back(wire
);
2290 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2292 AstNode
*lvalue
= new AstNode(AST_IDENTIFIER
);
2293 lvalue
->str
= wire
->str
;
2295 AstNode
*always
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
,
2296 new AstNode(AST_ASSIGN_EQ
, lvalue
, clone())));
2297 always
->children
[0]->children
[0]->was_checked
= true;
2299 current_ast_mod
->children
.push_back(always
);
2301 goto replace_fcall_with_id
;
2304 if (decl
->attributes
.count("\\via_celltype"))
2306 std::string celltype
= decl
->attributes
.at("\\via_celltype")->asAttrConst().decode_string();
2307 std::string outport
= str
;
2309 if (celltype
.find(' ') != std::string::npos
) {
2310 int pos
= celltype
.find(' ');
2311 outport
= RTLIL::escape_id(celltype
.substr(pos
+1));
2312 celltype
= RTLIL::escape_id(celltype
.substr(0, pos
));
2314 celltype
= RTLIL::escape_id(celltype
);
2316 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
));
2317 cell
->str
= prefix
.substr(0, GetSize(prefix
)-1);
2318 cell
->children
[0]->str
= celltype
;
2320 for (auto attr
: decl
->attributes
)
2321 if (attr
.first
.str().rfind("\\via_celltype_defparam_", 0) == 0)
2323 AstNode
*cell_arg
= new AstNode(AST_PARASET
, attr
.second
->clone());
2324 cell_arg
->str
= RTLIL::escape_id(attr
.first
.str().substr(strlen("\\via_celltype_defparam_")));
2325 cell
->children
.push_back(cell_arg
);
2328 for (auto child
: decl
->children
)
2329 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
|| (type
== AST_FCALL
&& child
->str
== str
)))
2331 AstNode
*wire
= child
->clone();
2332 wire
->str
= prefix
+ wire
->str
;
2334 wire
->is_input
= false;
2335 wire
->is_output
= false;
2336 current_ast_mod
->children
.push_back(wire
);
2337 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2339 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
2340 wire_id
->str
= wire
->str
;
2342 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
2344 AstNode
*arg
= children
[arg_count
++]->clone();
2345 AstNode
*assign
= child
->is_input
?
2346 new AstNode(AST_ASSIGN_EQ
, wire_id
->clone(), arg
) :
2347 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
->clone());
2348 assign
->children
[0]->was_checked
= true;
2350 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
2351 if (*it
!= current_block_child
)
2353 current_block
->children
.insert(it
, assign
);
2358 AstNode
*cell_arg
= new AstNode(AST_ARGUMENT
, wire_id
);
2359 cell_arg
->str
= child
->str
== str
? outport
: child
->str
;
2360 cell
->children
.push_back(cell_arg
);
2363 current_ast_mod
->children
.push_back(cell
);
2364 goto replace_fcall_with_id
;
2367 for (auto child
: decl
->children
)
2368 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
)
2370 AstNode
*wire
= nullptr;
2372 if (wire_cache
.count(child
->str
))
2374 wire
= wire_cache
.at(child
->str
);
2375 if (wire
->children
.empty()) {
2376 for (auto c
: child
->children
)
2377 wire
->children
.push_back(c
->clone());
2378 } else if (!child
->children
.empty()) {
2379 while (child
->simplify(true, false, false, stage
, -1, false, false)) { }
2380 if (GetSize(child
->children
) == GetSize(wire
->children
)) {
2381 for (int i
= 0; i
< GetSize(child
->children
); i
++)
2382 if (*child
->children
.at(i
) != *wire
->children
.at(i
))
2383 goto tcall_incompatible_wires
;
2385 tcall_incompatible_wires
:
2386 log_file_error(filename
, linenum
, "Incompatible re-declaration of wire %s.\n", child
->str
.c_str());
2392 wire
= child
->clone();
2393 wire
->str
= prefix
+ wire
->str
;
2395 wire
->is_input
= false;
2396 wire
->is_output
= false;
2397 wire
->is_reg
= true;
2398 wire
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
2399 wire_cache
[child
->str
] = wire
;
2401 current_ast_mod
->children
.push_back(wire
);
2402 added_mod_children
.push_back(wire
);
2405 if (child
->type
== AST_WIRE
)
2406 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2408 replace_rules
[child
->str
] = wire
->str
;
2409 current_scope
[wire
->str
] = wire
;
2411 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
2413 AstNode
*arg
= children
[arg_count
++]->clone();
2414 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
2415 wire_id
->str
= wire
->str
;
2416 AstNode
*assign
= child
->is_input
?
2417 new AstNode(AST_ASSIGN_EQ
, wire_id
, arg
) :
2418 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
);
2419 assign
->children
[0]->was_checked
= true;
2420 if (child
->is_input
)
2421 new_stmts
.push_back(assign
);
2423 output_assignments
.push_back(assign
);
2427 for (auto child
: added_mod_children
) {
2428 child
->replace_ids(prefix
, replace_rules
);
2429 while (child
->simplify(true, false, false, 1, -1, false, false)) { }
2432 for (auto child
: decl
->children
)
2433 if (child
->type
!= AST_WIRE
&& child
->type
!= AST_MEMORY
&& child
->type
!= AST_PARAMETER
&& child
->type
!= AST_LOCALPARAM
)
2435 AstNode
*stmt
= child
->clone();
2436 stmt
->replace_ids(prefix
, replace_rules
);
2437 new_stmts
.push_back(stmt
);
2440 new_stmts
.insert(new_stmts
.end(), output_assignments
.begin(), output_assignments
.end());
2442 for (auto it
= current_block
->children
.begin(); ; it
++) {
2443 log_assert(it
!= current_block
->children
.end());
2444 if (*it
== current_block_child
) {
2445 current_block
->children
.insert(it
, new_stmts
.begin(), new_stmts
.end());
2450 replace_fcall_with_id
:
2451 if (type
== AST_FCALL
) {
2453 type
= AST_IDENTIFIER
;
2456 if (type
== AST_TCALL
)
2458 did_something
= true;
2461 replace_fcall_later
:;
2463 // perform const folding when activated
2467 std::vector
<RTLIL::State
> tmp_bits
;
2468 RTLIL::Const (*const_func
)(const RTLIL::Const
&, const RTLIL::Const
&, bool, bool, int);
2469 RTLIL::Const dummy_arg
;
2473 case AST_IDENTIFIER
:
2474 if (current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
)) {
2475 if (current_scope
[str
]->children
[0]->type
== AST_CONSTANT
) {
2476 if (children
.size() != 0 && children
[0]->type
== AST_RANGE
&& children
[0]->range_valid
) {
2477 std::vector
<RTLIL::State
> data
;
2478 bool param_upto
= current_scope
[str
]->range_valid
&& current_scope
[str
]->range_swapped
;
2479 int param_offset
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_right
: 0;
2480 int param_width
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_left
- current_scope
[str
]->range_right
+ 1 :
2481 GetSize(current_scope
[str
]->children
[0]->bits
);
2482 int tmp_range_left
= children
[0]->range_left
, tmp_range_right
= children
[0]->range_right
;
2484 tmp_range_left
= (param_width
+ 2*param_offset
) - children
[0]->range_right
- 1;
2485 tmp_range_right
= (param_width
+ 2*param_offset
) - children
[0]->range_left
- 1;
2487 for (int i
= tmp_range_right
; i
<= tmp_range_left
; i
++) {
2488 int index
= i
- param_offset
;
2489 if (0 <= index
&& index
< param_width
)
2490 data
.push_back(current_scope
[str
]->children
[0]->bits
[index
]);
2492 data
.push_back(RTLIL::State::Sx
);
2494 newNode
= mkconst_bits(data
, false);
2496 if (children
.size() == 0)
2497 newNode
= current_scope
[str
]->children
[0]->clone();
2499 if (current_scope
[str
]->children
[0]->isConst())
2500 newNode
= current_scope
[str
]->children
[0]->clone();
2502 else if (at_zero
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_WIRE
|| current_scope
[str
]->type
== AST_AUTOWIRE
)) {
2503 newNode
= mkconst_int(0, sign_hint
, width_hint
);
2507 if (children
[0]->type
== AST_CONSTANT
) {
2508 RTLIL::Const y
= RTLIL::const_not(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
2509 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2513 case AST_TO_UNSIGNED
:
2514 if (children
[0]->type
== AST_CONSTANT
) {
2515 RTLIL::Const y
= children
[0]->bitsAsConst(width_hint
, sign_hint
);
2516 newNode
= mkconst_bits(y
.bits
, type
== AST_TO_SIGNED
);
2519 if (0) { case AST_BIT_AND
: const_func
= RTLIL::const_and
; }
2520 if (0) { case AST_BIT_OR
: const_func
= RTLIL::const_or
; }
2521 if (0) { case AST_BIT_XOR
: const_func
= RTLIL::const_xor
; }
2522 if (0) { case AST_BIT_XNOR
: const_func
= RTLIL::const_xnor
; }
2523 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2524 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
2525 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
2526 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2529 if (0) { case AST_REDUCE_AND
: const_func
= RTLIL::const_reduce_and
; }
2530 if (0) { case AST_REDUCE_OR
: const_func
= RTLIL::const_reduce_or
; }
2531 if (0) { case AST_REDUCE_XOR
: const_func
= RTLIL::const_reduce_xor
; }
2532 if (0) { case AST_REDUCE_XNOR
: const_func
= RTLIL::const_reduce_xnor
; }
2533 if (0) { case AST_REDUCE_BOOL
: const_func
= RTLIL::const_reduce_bool
; }
2534 if (children
[0]->type
== AST_CONSTANT
) {
2535 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), dummy_arg
, false, false, -1);
2536 newNode
= mkconst_bits(y
.bits
, false);
2540 if (children
[0]->type
== AST_CONSTANT
) {
2541 RTLIL::Const y
= RTLIL::const_logic_not(RTLIL::Const(children
[0]->bits
), dummy_arg
, children
[0]->is_signed
, false, -1);
2542 newNode
= mkconst_bits(y
.bits
, false);
2544 if (children
[0]->isConst()) {
2545 newNode
= mkconst_int(children
[0]->asReal(sign_hint
) == 0, false, 1);
2548 if (0) { case AST_LOGIC_AND
: const_func
= RTLIL::const_logic_and
; }
2549 if (0) { case AST_LOGIC_OR
: const_func
= RTLIL::const_logic_or
; }
2550 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2551 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), RTLIL::Const(children
[1]->bits
),
2552 children
[0]->is_signed
, children
[1]->is_signed
, -1);
2553 newNode
= mkconst_bits(y
.bits
, false);
2555 if (children
[0]->isConst() && children
[1]->isConst()) {
2556 if (type
== AST_LOGIC_AND
)
2557 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) && (children
[1]->asReal(sign_hint
) != 0), false, 1);
2559 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) || (children
[1]->asReal(sign_hint
) != 0), false, 1);
2562 if (0) { case AST_SHIFT_LEFT
: const_func
= RTLIL::const_shl
; }
2563 if (0) { case AST_SHIFT_RIGHT
: const_func
= RTLIL::const_shr
; }
2564 if (0) { case AST_SHIFT_SLEFT
: const_func
= RTLIL::const_sshl
; }
2565 if (0) { case AST_SHIFT_SRIGHT
: const_func
= RTLIL::const_sshr
; }
2566 if (0) { case AST_POW
: const_func
= RTLIL::const_pow
; }
2567 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2568 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
2569 RTLIL::Const(children
[1]->bits
), sign_hint
, type
== AST_POW
? children
[1]->is_signed
: false, width_hint
);
2570 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2572 if (type
== AST_POW
&& children
[0]->isConst() && children
[1]->isConst()) {
2573 newNode
= new AstNode(AST_REALVALUE
);
2574 newNode
->realvalue
= pow(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
));
2577 if (0) { case AST_LT
: const_func
= RTLIL::const_lt
; }
2578 if (0) { case AST_LE
: const_func
= RTLIL::const_le
; }
2579 if (0) { case AST_EQ
: const_func
= RTLIL::const_eq
; }
2580 if (0) { case AST_NE
: const_func
= RTLIL::const_ne
; }
2581 if (0) { case AST_EQX
: const_func
= RTLIL::const_eqx
; }
2582 if (0) { case AST_NEX
: const_func
= RTLIL::const_nex
; }
2583 if (0) { case AST_GE
: const_func
= RTLIL::const_ge
; }
2584 if (0) { case AST_GT
: const_func
= RTLIL::const_gt
; }
2585 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2586 int cmp_width
= max(children
[0]->bits
.size(), children
[1]->bits
.size());
2587 bool cmp_signed
= children
[0]->is_signed
&& children
[1]->is_signed
;
2588 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(cmp_width
, cmp_signed
),
2589 children
[1]->bitsAsConst(cmp_width
, cmp_signed
), cmp_signed
, cmp_signed
, 1);
2590 newNode
= mkconst_bits(y
.bits
, false);
2592 if (children
[0]->isConst() && children
[1]->isConst()) {
2593 bool cmp_signed
= (children
[0]->type
== AST_REALVALUE
|| children
[0]->is_signed
) && (children
[1]->type
== AST_REALVALUE
|| children
[1]->is_signed
);
2595 case AST_LT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) < children
[1]->asReal(cmp_signed
), false, 1); break;
2596 case AST_LE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) <= children
[1]->asReal(cmp_signed
), false, 1); break;
2597 case AST_EQ
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
2598 case AST_NE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
2599 case AST_EQX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
2600 case AST_NEX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
2601 case AST_GE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) >= children
[1]->asReal(cmp_signed
), false, 1); break;
2602 case AST_GT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) > children
[1]->asReal(cmp_signed
), false, 1); break;
2603 default: log_abort();
2607 if (0) { case AST_ADD
: const_func
= RTLIL::const_add
; }
2608 if (0) { case AST_SUB
: const_func
= RTLIL::const_sub
; }
2609 if (0) { case AST_MUL
: const_func
= RTLIL::const_mul
; }
2610 if (0) { case AST_DIV
: const_func
= RTLIL::const_div
; }
2611 if (0) { case AST_MOD
: const_func
= RTLIL::const_mod
; }
2612 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2613 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
2614 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
2615 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2617 if (children
[0]->isConst() && children
[1]->isConst()) {
2618 newNode
= new AstNode(AST_REALVALUE
);
2620 case AST_ADD
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) + children
[1]->asReal(sign_hint
); break;
2621 case AST_SUB
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) - children
[1]->asReal(sign_hint
); break;
2622 case AST_MUL
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) * children
[1]->asReal(sign_hint
); break;
2623 case AST_DIV
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) / children
[1]->asReal(sign_hint
); break;
2624 case AST_MOD
: newNode
->realvalue
= fmod(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
)); break;
2625 default: log_abort();
2629 if (0) { case AST_POS
: const_func
= RTLIL::const_pos
; }
2630 if (0) { case AST_NEG
: const_func
= RTLIL::const_neg
; }
2631 if (children
[0]->type
== AST_CONSTANT
) {
2632 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
2633 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2635 if (children
[0]->isConst()) {
2636 newNode
= new AstNode(AST_REALVALUE
);
2637 if (type
== AST_POS
)
2638 newNode
->realvalue
= +children
[0]->asReal(sign_hint
);
2640 newNode
->realvalue
= -children
[0]->asReal(sign_hint
);
2644 if (children
[0]->isConst())
2646 bool found_sure_true
= false;
2647 bool found_maybe_true
= false;
2649 if (children
[0]->type
== AST_CONSTANT
)
2650 for (auto &bit
: children
[0]->bits
) {
2651 if (bit
== RTLIL::State::S1
)
2652 found_sure_true
= true;
2653 if (bit
> RTLIL::State::S1
)
2654 found_maybe_true
= true;
2657 found_sure_true
= children
[0]->asReal(sign_hint
) != 0;
2659 AstNode
*choice
= NULL
, *not_choice
= NULL
;
2660 if (found_sure_true
)
2661 choice
= children
[1], not_choice
= children
[2];
2662 else if (!found_maybe_true
)
2663 choice
= children
[2], not_choice
= children
[1];
2665 if (choice
!= NULL
) {
2666 if (choice
->type
== AST_CONSTANT
) {
2667 int other_width_hint
= width_hint
;
2668 bool other_sign_hint
= sign_hint
, other_real
= false;
2669 not_choice
->detectSignWidth(other_width_hint
, other_sign_hint
, &other_real
);
2671 newNode
= new AstNode(AST_REALVALUE
);
2672 choice
->detectSignWidth(width_hint
, sign_hint
);
2673 newNode
->realvalue
= choice
->asReal(sign_hint
);
2675 RTLIL::Const y
= choice
->bitsAsConst(width_hint
, sign_hint
);
2676 if (choice
->is_string
&& y
.bits
.size() % 8 == 0 && sign_hint
== false)
2677 newNode
= mkconst_str(y
.bits
);
2679 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2682 if (choice
->isConst()) {
2683 newNode
= choice
->clone();
2685 } else if (children
[1]->type
== AST_CONSTANT
&& children
[2]->type
== AST_CONSTANT
) {
2686 RTLIL::Const a
= children
[1]->bitsAsConst(width_hint
, sign_hint
);
2687 RTLIL::Const b
= children
[2]->bitsAsConst(width_hint
, sign_hint
);
2688 log_assert(a
.bits
.size() == b
.bits
.size());
2689 for (size_t i
= 0; i
< a
.bits
.size(); i
++)
2690 if (a
.bits
[i
] != b
.bits
[i
])
2691 a
.bits
[i
] = RTLIL::State::Sx
;
2692 newNode
= mkconst_bits(a
.bits
, sign_hint
);
2693 } else if (children
[1]->isConst() && children
[2]->isConst()) {
2694 newNode
= new AstNode(AST_REALVALUE
);
2695 if (children
[1]->asReal(sign_hint
) == children
[2]->asReal(sign_hint
))
2696 newNode
->realvalue
= children
[1]->asReal(sign_hint
);
2698 // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
2699 // the data type in question should be returned if the ?: is ambiguous. The
2700 // value in Table 7-1 for the 'real' type is 0.0.
2701 newNode
->realvalue
= 0.0;
2706 string_op
= !children
.empty();
2707 for (auto it
= children
.begin(); it
!= children
.end(); it
++) {
2708 if ((*it
)->type
!= AST_CONSTANT
)
2710 if (!(*it
)->is_string
)
2712 tmp_bits
.insert(tmp_bits
.end(), (*it
)->bits
.begin(), (*it
)->bits
.end());
2714 newNode
= string_op
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
2717 if (children
.at(0)->type
!= AST_CONSTANT
|| children
.at(1)->type
!= AST_CONSTANT
)
2719 for (int i
= 0; i
< children
[0]->bitsAsConst().as_int(); i
++)
2720 tmp_bits
.insert(tmp_bits
.end(), children
.at(1)->bits
.begin(), children
.at(1)->bits
.end());
2721 newNode
= children
.at(1)->is_string
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
2729 // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
2732 // fprintf(stderr, "----\n");
2733 // dumpAst(stderr, "- ");
2734 // newNode->dumpAst(stderr, "+ ");
2735 log_assert(newNode
!= NULL
);
2736 newNode
->filename
= filename
;
2737 newNode
->linenum
= linenum
;
2738 newNode
->cloneInto(this);
2740 did_something
= true;
2746 recursion_counter
--;
2747 return did_something
;
2750 static void replace_result_wire_name_in_function(AstNode
*node
, std::string
&from
, std::string
&to
)
2752 for (auto &it
: node
->children
)
2753 replace_result_wire_name_in_function(it
, from
, to
);
2754 if (node
->str
== from
)
2758 // replace a readmem[bh] TCALL ast node with a block of memory assignments
2759 AstNode
*AstNode::readmem(bool is_readmemh
, std::string mem_filename
, AstNode
*memory
, int start_addr
, int finish_addr
, bool unconditional_init
)
2761 int mem_width
, mem_size
, addr_bits
;
2762 memory
->meminfo(mem_width
, mem_size
, addr_bits
);
2764 AstNode
*block
= new AstNode(AST_BLOCK
);
2766 AstNode
*meminit
= nullptr;
2767 int next_meminit_cursor
=0;
2768 vector
<State
> meminit_bits
;
2772 f
.open(mem_filename
.c_str());
2773 yosys_input_files
.insert(mem_filename
);
2776 log_file_error(filename
, linenum
, "Can not open file `%s` for %s.\n", mem_filename
.c_str(), str
.c_str());
2778 log_assert(GetSize(memory
->children
) == 2 && memory
->children
[1]->type
== AST_RANGE
&& memory
->children
[1]->range_valid
);
2779 int range_left
= memory
->children
[1]->range_left
, range_right
= memory
->children
[1]->range_right
;
2780 int range_min
= min(range_left
, range_right
), range_max
= max(range_left
, range_right
);
2783 start_addr
= range_min
;
2785 if (finish_addr
< 0)
2786 finish_addr
= range_max
+ 1;
2788 bool in_comment
= false;
2789 int increment
= start_addr
<= finish_addr
? +1 : -1;
2790 int cursor
= start_addr
;
2794 std::string line
, token
;
2795 std::getline(f
, line
);
2797 for (int i
= 0; i
< GetSize(line
); i
++) {
2798 if (in_comment
&& line
.substr(i
, 2) == "*/") {
2804 if (!in_comment
&& line
.substr(i
, 2) == "/*")
2812 token
= next_token(line
, " \t\r\n");
2813 if (token
.empty() || token
.substr(0, 2) == "//")
2816 if (token
[0] == '@') {
2817 token
= token
.substr(1);
2818 const char *nptr
= token
.c_str();
2820 cursor
= strtol(nptr
, &endptr
, 16);
2821 if (!*nptr
|| *endptr
)
2822 log_file_error(filename
, linenum
, "Can not parse address `%s` for %s.\n", nptr
, str
.c_str());
2826 AstNode
*value
= VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width
, is_readmemh
? 'h' : 'b') + token
);
2828 if (unconditional_init
)
2830 if (meminit
== nullptr || cursor
!= next_meminit_cursor
)
2832 if (meminit
!= nullptr) {
2833 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
2834 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
2837 meminit
= new AstNode(AST_MEMINIT
);
2838 meminit
->children
.push_back(AstNode::mkconst_int(cursor
, false));
2839 meminit
->children
.push_back(nullptr);
2840 meminit
->children
.push_back(nullptr);
2841 meminit
->str
= memory
->str
;
2842 meminit
->id2ast
= memory
;
2843 meminit_bits
.clear();
2846 current_ast_mod
->children
.push_back(meminit
);
2847 next_meminit_cursor
= cursor
;
2851 next_meminit_cursor
++;
2852 meminit_bits
.insert(meminit_bits
.end(), value
->bits
.begin(), value
->bits
.end());
2857 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
, false))), value
));
2858 block
->children
.back()->children
[0]->str
= memory
->str
;
2859 block
->children
.back()->children
[0]->id2ast
= memory
;
2860 block
->children
.back()->children
[0]->was_checked
= true;
2863 cursor
+= increment
;
2864 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
2868 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
2872 if (meminit
!= nullptr) {
2873 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
2874 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
2880 // annotate the names of all wires and other named objects in a generate block
2881 void AstNode::expand_genblock(std::string index_var
, std::string prefix
, std::map
<std::string
, std::string
> &name_map
)
2883 if (!index_var
.empty() && type
== AST_IDENTIFIER
&& str
== index_var
) {
2884 current_scope
[index_var
]->children
[0]->cloneInto(this);
2888 if ((type
== AST_IDENTIFIER
|| type
== AST_FCALL
|| type
== AST_TCALL
) && name_map
.count(str
) > 0)
2889 str
= name_map
[str
];
2891 std::map
<std::string
, std::string
> backup_name_map
;
2893 for (size_t i
= 0; i
< children
.size(); i
++) {
2894 AstNode
*child
= children
[i
];
2895 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
||
2896 child
->type
== AST_FUNCTION
|| child
->type
== AST_TASK
|| child
->type
== AST_CELL
) {
2897 if (backup_name_map
.size() == 0)
2898 backup_name_map
= name_map
;
2899 std::string new_name
= prefix
[0] == '\\' ? prefix
.substr(1) : prefix
;
2900 size_t pos
= child
->str
.rfind('.');
2901 if (pos
== std::string::npos
)
2902 pos
= child
->str
[0] == '\\' && prefix
[0] == '\\' ? 1 : 0;
2905 new_name
= child
->str
.substr(0, pos
) + new_name
+ child
->str
.substr(pos
);
2906 if (new_name
[0] != '$' && new_name
[0] != '\\')
2907 new_name
= prefix
[0] + new_name
;
2908 name_map
[child
->str
] = new_name
;
2909 if (child
->type
== AST_FUNCTION
)
2910 replace_result_wire_name_in_function(child
, child
->str
, new_name
);
2912 child
->str
= new_name
;
2913 current_scope
[new_name
] = child
;
2917 for (size_t i
= 0; i
< children
.size(); i
++) {
2918 AstNode
*child
= children
[i
];
2919 // AST_PREFIX member names should not be prefixed; a nested AST_PREFIX
2920 // still needs to recursed-into
2921 if (type
== AST_PREFIX
&& i
== 1 && child
->type
== AST_IDENTIFIER
)
2923 if (child
->type
!= AST_FUNCTION
&& child
->type
!= AST_TASK
)
2924 child
->expand_genblock(index_var
, prefix
, name_map
);
2927 if (backup_name_map
.size() > 0)
2928 name_map
.swap(backup_name_map
);
2931 // rename stuff (used when tasks of functions are instantiated)
2932 void AstNode::replace_ids(const std::string
&prefix
, const std::map
<std::string
, std::string
> &rules
)
2934 if (type
== AST_BLOCK
)
2936 std::map
<std::string
, std::string
> new_rules
= rules
;
2937 std::string new_prefix
= prefix
+ str
;
2939 for (auto child
: children
)
2940 if (child
->type
== AST_WIRE
) {
2941 new_rules
[child
->str
] = new_prefix
+ child
->str
;
2942 child
->str
= new_prefix
+ child
->str
;
2945 for (auto child
: children
)
2946 if (child
->type
!= AST_WIRE
)
2947 child
->replace_ids(new_prefix
, new_rules
);
2951 if (type
== AST_IDENTIFIER
&& rules
.count(str
) > 0)
2952 str
= rules
.at(str
);
2953 for (auto child
: children
)
2954 child
->replace_ids(prefix
, rules
);
2958 // helper function for mem2reg_as_needed_pass1
2959 static void mark_memories_assign_lhs_complex(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
2960 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, AstNode
*that
)
2962 for (auto &child
: that
->children
)
2963 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, child
);
2965 if (that
->type
== AST_IDENTIFIER
&& that
->id2ast
&& that
->id2ast
->type
== AST_MEMORY
) {
2966 AstNode
*mem
= that
->id2ast
;
2967 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_CMPLX_LHS
))
2968 mem2reg_places
[mem
].insert(stringf("%s:%d", that
->filename
.c_str(), that
->linenum
));
2969 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CMPLX_LHS
;
2973 // find memories that should be replaced by registers
2974 void AstNode::mem2reg_as_needed_pass1(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
2975 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, dict
<AstNode
*, uint32_t> &proc_flags
, uint32_t &flags
)
2977 uint32_t children_flags
= 0;
2978 int lhs_children_counter
= 0;
2980 if (type
== AST_ASSIGN
|| type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
)
2982 // mark all memories that are used in a complex expression on the left side of an assignment
2983 for (auto &lhs_child
: children
[0]->children
)
2984 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, lhs_child
);
2986 if (children
[0]->type
== AST_IDENTIFIER
&& children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
)
2988 AstNode
*mem
= children
[0]->id2ast
;
2990 // activate mem2reg if this is assigned in an async proc
2991 if (flags
& AstNode::MEM2REG_FL_ASYNC
) {
2992 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ASYNC
))
2993 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
2994 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ASYNC
;
2997 // remember if this is assigned blocking (=)
2998 if (type
== AST_ASSIGN_EQ
) {
2999 if (!(proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
))
3000 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3001 proc_flags
[mem
] |= AstNode::MEM2REG_FL_EQ1
;
3004 // for proper (non-init) writes: remember if this is a constant index or not
3005 if ((flags
& MEM2REG_FL_INIT
) == 0) {
3006 if (children
[0]->children
.size() && children
[0]->children
[0]->type
== AST_RANGE
&& children
[0]->children
[0]->children
.size()) {
3007 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
)
3008 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CONST_LHS
;
3010 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_VAR_LHS
;
3014 // remember where this is
3015 if (flags
& MEM2REG_FL_INIT
) {
3016 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_INIT
))
3017 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3018 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_INIT
;
3020 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ELSE
))
3021 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3022 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ELSE
;
3026 lhs_children_counter
= 1;
3029 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
)
3031 AstNode
*mem
= id2ast
;
3033 // flag if used after blocking assignment (in same proc)
3034 if ((proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
) && !(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_EQ2
)) {
3035 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3036 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_EQ2
;
3040 // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg'
3041 if (type
== AST_MEMORY
&& (get_bool_attribute("\\mem2reg") || (flags
& AstNode::MEM2REG_FL_ALL
) || !is_reg
))
3042 mem2reg_candidates
[this] |= AstNode::MEM2REG_FL_FORCED
;
3044 if (type
== AST_MODULE
&& get_bool_attribute("\\mem2reg"))
3045 children_flags
|= AstNode::MEM2REG_FL_ALL
;
3047 dict
<AstNode
*, uint32_t> *proc_flags_p
= NULL
;
3049 if (type
== AST_ALWAYS
) {
3050 int count_edge_events
= 0;
3051 for (auto child
: children
)
3052 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
3053 count_edge_events
++;
3054 if (count_edge_events
!= 1)
3055 children_flags
|= AstNode::MEM2REG_FL_ASYNC
;
3056 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
3059 if (type
== AST_INITIAL
) {
3060 children_flags
|= AstNode::MEM2REG_FL_INIT
;
3061 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
3064 uint32_t backup_flags
= flags
;
3065 flags
|= children_flags
;
3066 log_assert((flags
& ~0x000000ff) == 0);
3068 for (auto child
: children
)
3070 if (lhs_children_counter
> 0) {
3071 lhs_children_counter
--;
3072 if (child
->children
.size() && child
->children
[0]->type
== AST_RANGE
&& child
->children
[0]->children
.size()) {
3073 for (auto c
: child
->children
[0]->children
) {
3075 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
3077 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
3082 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
3084 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
3087 flags
&= ~children_flags
| backup_flags
;
3091 for (auto it
: *proc_flags_p
)
3092 log_assert((it
.second
& ~0xff000000) == 0);
3094 delete proc_flags_p
;
3098 bool AstNode::mem2reg_check(pool
<AstNode
*> &mem2reg_set
)
3100 if (type
!= AST_IDENTIFIER
|| !id2ast
|| !mem2reg_set
.count(id2ast
))
3103 if (children
.empty() || children
[0]->type
!= AST_RANGE
|| GetSize(children
[0]->children
) != 1)
3104 log_file_error(filename
, linenum
, "Invalid array access.\n");
3109 void AstNode::mem2reg_remove(pool
<AstNode
*> &mem2reg_set
, vector
<AstNode
*> &delnodes
)
3111 log_assert(mem2reg_set
.count(this) == 0);
3113 if (mem2reg_set
.count(id2ast
))
3116 for (size_t i
= 0; i
< children
.size(); i
++) {
3117 if (mem2reg_set
.count(children
[i
]) > 0) {
3118 delnodes
.push_back(children
[i
]);
3119 children
.erase(children
.begin() + (i
--));
3121 children
[i
]->mem2reg_remove(mem2reg_set
, delnodes
);
3126 // actually replace memories with registers
3127 bool AstNode::mem2reg_as_needed_pass2(pool
<AstNode
*> &mem2reg_set
, AstNode
*mod
, AstNode
*block
, AstNode
*&async_block
)
3129 bool did_something
= false;
3131 if (type
== AST_BLOCK
)
3134 if (type
== AST_FUNCTION
|| type
== AST_TASK
)
3137 if (type
== AST_MEMINIT
&& id2ast
&& mem2reg_set
.count(id2ast
))
3139 log_assert(children
[0]->type
== AST_CONSTANT
);
3140 log_assert(children
[1]->type
== AST_CONSTANT
);
3141 log_assert(children
[2]->type
== AST_CONSTANT
);
3143 int cursor
= children
[0]->asInt(false);
3144 Const data
= children
[1]->bitsAsConst();
3145 int length
= children
[2]->asInt(false);
3149 AstNode
*block
= new AstNode(AST_INITIAL
, new AstNode(AST_BLOCK
));
3150 mod
->children
.push_back(block
);
3151 block
= block
->children
[0];
3153 int wordsz
= GetSize(data
) / length
;
3155 for (int i
= 0; i
< length
; i
++) {
3156 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+i
, false))), mkconst_bits(data
.extract(i
*wordsz
, wordsz
).bits
, false)));
3157 block
->children
.back()->children
[0]->str
= str
;
3158 block
->children
.back()->children
[0]->id2ast
= id2ast
;
3159 block
->children
.back()->children
[0]->was_checked
= true;
3163 AstNode
*newNode
= new AstNode(AST_NONE
);
3164 newNode
->cloneInto(this);
3167 did_something
= true;
3170 if (type
== AST_ASSIGN
&& block
== NULL
&& children
[0]->mem2reg_check(mem2reg_set
))
3172 if (async_block
== NULL
) {
3173 async_block
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
3174 mod
->children
.push_back(async_block
);
3177 AstNode
*newNode
= clone();
3178 newNode
->type
= AST_ASSIGN_EQ
;
3179 newNode
->children
[0]->was_checked
= true;
3180 async_block
->children
[0]->children
.push_back(newNode
);
3182 newNode
= new AstNode(AST_NONE
);
3183 newNode
->cloneInto(this);
3186 did_something
= true;
3189 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->mem2reg_check(mem2reg_set
) &&
3190 children
[0]->children
[0]->children
[0]->type
!= AST_CONSTANT
)
3192 std::stringstream sstr
;
3193 sstr
<< "$mem2reg_wr$" << children
[0]->str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
3194 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
3196 int mem_width
, mem_size
, addr_bits
;
3197 bool mem_signed
= children
[0]->id2ast
->is_signed
;
3198 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
3200 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
3201 wire_addr
->str
= id_addr
;
3202 wire_addr
->is_reg
= true;
3203 wire_addr
->was_checked
= true;
3204 wire_addr
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3205 mod
->children
.push_back(wire_addr
);
3206 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
3208 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
3209 wire_data
->str
= id_data
;
3210 wire_data
->is_reg
= true;
3211 wire_data
->was_checked
= true;
3212 wire_data
->is_signed
= mem_signed
;
3213 wire_data
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3214 mod
->children
.push_back(wire_data
);
3215 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
3217 log_assert(block
!= NULL
);
3218 size_t assign_idx
= 0;
3219 while (assign_idx
< block
->children
.size() && block
->children
[assign_idx
] != this)
3221 log_assert(assign_idx
< block
->children
.size());
3223 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
3224 assign_addr
->children
[0]->str
= id_addr
;
3225 assign_addr
->children
[0]->was_checked
= true;
3226 block
->children
.insert(block
->children
.begin()+assign_idx
+1, assign_addr
);
3228 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
3229 case_node
->children
[0]->str
= id_addr
;
3230 for (int i
= 0; i
< mem_size
; i
++) {
3231 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->children
[0]->integer
) != i
)
3233 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
3234 AstNode
*assign_reg
= new AstNode(type
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
3235 if (children
[0]->children
.size() == 2)
3236 assign_reg
->children
[0]->children
.push_back(children
[0]->children
[1]->clone());
3237 assign_reg
->children
[0]->str
= stringf("%s[%d]", children
[0]->str
.c_str(), i
);
3238 assign_reg
->children
[1]->str
= id_data
;
3239 cond_node
->children
[1]->children
.push_back(assign_reg
);
3240 case_node
->children
.push_back(cond_node
);
3242 block
->children
.insert(block
->children
.begin()+assign_idx
+2, case_node
);
3244 children
[0]->delete_children();
3245 children
[0]->range_valid
= false;
3246 children
[0]->id2ast
= NULL
;
3247 children
[0]->str
= id_data
;
3248 type
= AST_ASSIGN_EQ
;
3249 children
[0]->was_checked
= true;
3251 did_something
= true;
3254 if (mem2reg_check(mem2reg_set
))
3256 AstNode
*bit_part_sel
= NULL
;
3257 if (children
.size() == 2)
3258 bit_part_sel
= children
[1]->clone();
3260 if (children
[0]->children
[0]->type
== AST_CONSTANT
)
3262 int id
= children
[0]->children
[0]->integer
;
3263 str
= stringf("%s[%d]", str
.c_str(), id
);
3266 range_valid
= false;
3271 std::stringstream sstr
;
3272 sstr
<< "$mem2reg_rd$" << str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
3273 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
3275 int mem_width
, mem_size
, addr_bits
;
3276 bool mem_signed
= id2ast
->is_signed
;
3277 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
3279 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
3280 wire_addr
->str
= id_addr
;
3281 wire_addr
->is_reg
= true;
3282 wire_addr
->was_checked
= true;
3284 wire_addr
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3285 mod
->children
.push_back(wire_addr
);
3286 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
3288 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
3289 wire_data
->str
= id_data
;
3290 wire_data
->is_reg
= true;
3291 wire_data
->was_checked
= true;
3292 wire_data
->is_signed
= mem_signed
;
3294 wire_data
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3295 mod
->children
.push_back(wire_data
);
3296 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
3298 AstNode
*assign_addr
= new AstNode(block
? AST_ASSIGN_EQ
: AST_ASSIGN
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->clone());
3299 assign_addr
->children
[0]->str
= id_addr
;
3300 assign_addr
->children
[0]->was_checked
= true;
3302 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
3303 case_node
->children
[0]->str
= id_addr
;
3305 for (int i
= 0; i
< mem_size
; i
++) {
3306 if (children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->integer
) != i
)
3308 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
3309 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
3310 assign_reg
->children
[0]->str
= id_data
;
3311 assign_reg
->children
[0]->was_checked
= true;
3312 assign_reg
->children
[1]->str
= stringf("%s[%d]", str
.c_str(), i
);
3313 cond_node
->children
[1]->children
.push_back(assign_reg
);
3314 case_node
->children
.push_back(cond_node
);
3317 std::vector
<RTLIL::State
> x_bits
;
3318 for (int i
= 0; i
< mem_width
; i
++)
3319 x_bits
.push_back(RTLIL::State::Sx
);
3321 AstNode
*cond_node
= new AstNode(AST_COND
, new AstNode(AST_DEFAULT
), new AstNode(AST_BLOCK
));
3322 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), AstNode::mkconst_bits(x_bits
, false));
3323 assign_reg
->children
[0]->str
= id_data
;
3324 assign_reg
->children
[0]->was_checked
= true;
3325 cond_node
->children
[1]->children
.push_back(assign_reg
);
3326 case_node
->children
.push_back(cond_node
);
3330 size_t assign_idx
= 0;
3331 while (assign_idx
< block
->children
.size() && !block
->children
[assign_idx
]->contains(this))
3333 log_assert(assign_idx
< block
->children
.size());
3334 block
->children
.insert(block
->children
.begin()+assign_idx
, case_node
);
3335 block
->children
.insert(block
->children
.begin()+assign_idx
, assign_addr
);
3339 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
3340 proc
->children
[0]->children
.push_back(case_node
);
3341 mod
->children
.push_back(proc
);
3342 mod
->children
.push_back(assign_addr
);
3346 range_valid
= false;
3352 children
.push_back(bit_part_sel
);
3354 did_something
= true;
3357 log_assert(id2ast
== NULL
|| mem2reg_set
.count(id2ast
) == 0);
3359 auto children_list
= children
;
3360 for (size_t i
= 0; i
< children_list
.size(); i
++)
3361 if (children_list
[i
]->mem2reg_as_needed_pass2(mem2reg_set
, mod
, block
, async_block
))
3362 did_something
= true;
3364 return did_something
;
3367 // calculate memory dimensions
3368 void AstNode::meminfo(int &mem_width
, int &mem_size
, int &addr_bits
)
3370 log_assert(type
== AST_MEMORY
);
3372 mem_width
= children
[0]->range_left
- children
[0]->range_right
+ 1;
3373 mem_size
= children
[1]->range_left
- children
[1]->range_right
;
3377 mem_size
+= min(children
[1]->range_left
, children
[1]->range_right
) + 1;
3380 while ((1 << addr_bits
) < mem_size
)
3384 bool AstNode::has_const_only_constructs(bool &recommend_const_eval
)
3386 if (type
== AST_FOR
)
3387 recommend_const_eval
= true;
3388 if (type
== AST_WHILE
|| type
== AST_REPEAT
)
3390 if (type
== AST_FCALL
&& current_scope
.count(str
))
3391 if (current_scope
[str
]->has_const_only_constructs(recommend_const_eval
))
3393 for (auto child
: children
)
3394 if (child
->AstNode::has_const_only_constructs(recommend_const_eval
))
3399 bool AstNode::is_simple_const_expr()
3401 if (type
== AST_IDENTIFIER
)
3403 for (auto child
: children
)
3404 if (!child
->is_simple_const_expr())
3409 // helper function for AstNode::eval_const_function()
3410 void AstNode::replace_variables(std::map
<std::string
, AstNode::varinfo_t
> &variables
, AstNode
*fcall
)
3412 if (type
== AST_IDENTIFIER
&& variables
.count(str
)) {
3413 int offset
= variables
.at(str
).offset
, width
= variables
.at(str
).val
.bits
.size();
3414 if (!children
.empty()) {
3415 if (children
.size() != 1 || children
.at(0)->type
!= AST_RANGE
)
3416 log_file_error(filename
, linenum
, "Memory access in constant function is not supported\n%s:%d: ...called from here.\n",
3417 fcall
->filename
.c_str(), fcall
->linenum
);
3418 children
.at(0)->replace_variables(variables
, fcall
);
3419 while (simplify(true, false, false, 1, -1, false, true)) { }
3420 if (!children
.at(0)->range_valid
)
3421 log_file_error(filename
, linenum
, "Non-constant range\n%s:%d: ... called from here.\n",
3422 fcall
->filename
.c_str(), fcall
->linenum
);
3423 offset
= min(children
.at(0)->range_left
, children
.at(0)->range_right
);
3424 width
= min(std::abs(children
.at(0)->range_left
- children
.at(0)->range_right
) + 1, width
);
3426 offset
-= variables
.at(str
).offset
;
3427 std::vector
<RTLIL::State
> &var_bits
= variables
.at(str
).val
.bits
;
3428 std::vector
<RTLIL::State
> new_bits(var_bits
.begin() + offset
, var_bits
.begin() + offset
+ width
);
3429 AstNode
*newNode
= mkconst_bits(new_bits
, variables
.at(str
).is_signed
);
3430 newNode
->cloneInto(this);
3435 for (auto &child
: children
)
3436 child
->replace_variables(variables
, fcall
);
3439 // evaluate functions with all-const arguments
3440 AstNode
*AstNode::eval_const_function(AstNode
*fcall
)
3442 std::map
<std::string
, AstNode
*> backup_scope
;
3443 std::map
<std::string
, AstNode::varinfo_t
> variables
;
3444 bool delete_temp_block
= false;
3445 AstNode
*block
= NULL
;
3448 for (auto child
: children
)
3450 if (child
->type
== AST_BLOCK
)
3452 log_assert(block
== NULL
);
3457 if (child
->type
== AST_WIRE
)
3459 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
3460 if (!child
->range_valid
)
3461 log_file_error(child
->filename
, child
->linenum
, "Can't determine size of variable %s\n%s:%d: ... called from here.\n",
3462 child
->str
.c_str(), fcall
->filename
.c_str(), fcall
->linenum
);
3463 variables
[child
->str
].val
= RTLIL::Const(RTLIL::State::Sx
, abs(child
->range_left
- child
->range_right
)+1);
3464 variables
[child
->str
].offset
= min(child
->range_left
, child
->range_right
);
3465 variables
[child
->str
].is_signed
= child
->is_signed
;
3466 if (child
->is_input
&& argidx
< fcall
->children
.size())
3467 variables
[child
->str
].val
= fcall
->children
.at(argidx
++)->bitsAsConst(variables
[child
->str
].val
.bits
.size());
3468 backup_scope
[child
->str
] = current_scope
[child
->str
];
3469 current_scope
[child
->str
] = child
;
3473 log_assert(block
== NULL
);
3474 delete_temp_block
= true;
3475 block
= new AstNode(AST_BLOCK
);
3476 block
->children
.push_back(child
->clone());
3479 log_assert(block
!= NULL
);
3480 log_assert(variables
.count(str
) != 0);
3482 while (!block
->children
.empty())
3484 AstNode
*stmt
= block
->children
.front();
3487 log("-----------------------------------\n");
3488 for (auto &it
: variables
)
3489 log("%20s %40s\n", it
.first
.c_str(), log_signal(it
.second
.val
));
3490 stmt
->dumpAst(NULL
, "stmt> ");
3493 if (stmt
->type
== AST_ASSIGN_EQ
)
3495 if (stmt
->children
.at(0)->type
== AST_IDENTIFIER
&& stmt
->children
.at(0)->children
.size() != 0 &&
3496 stmt
->children
.at(0)->children
.at(0)->type
== AST_RANGE
)
3497 stmt
->children
.at(0)->children
.at(0)->replace_variables(variables
, fcall
);
3498 stmt
->children
.at(1)->replace_variables(variables
, fcall
);
3499 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
3501 if (stmt
->type
!= AST_ASSIGN_EQ
)
3504 if (stmt
->children
.at(1)->type
!= AST_CONSTANT
)
3505 log_file_error(stmt
->filename
, stmt
->linenum
, "Non-constant expression in constant function\n%s:%d: ... called from here. X\n",
3506 fcall
->filename
.c_str(), fcall
->linenum
);
3508 if (stmt
->children
.at(0)->type
!= AST_IDENTIFIER
)
3509 log_file_error(stmt
->filename
, stmt
->linenum
, "Unsupported composite left hand side in constant function\n%s:%d: ... called from here.\n",
3510 fcall
->filename
.c_str(), fcall
->linenum
);
3512 if (!variables
.count(stmt
->children
.at(0)->str
))
3513 log_file_error(stmt
->filename
, stmt
->linenum
, "Assignment to non-local variable in constant function\n%s:%d: ... called from here.\n",
3514 fcall
->filename
.c_str(), fcall
->linenum
);
3516 if (stmt
->children
.at(0)->children
.empty()) {
3517 variables
[stmt
->children
.at(0)->str
].val
= stmt
->children
.at(1)->bitsAsConst(variables
[stmt
->children
.at(0)->str
].val
.bits
.size());
3519 AstNode
*range
= stmt
->children
.at(0)->children
.at(0);
3520 if (!range
->range_valid
)
3521 log_file_error(range
->filename
, range
->linenum
, "Non-constant range\n%s:%d: ... called from here.\n",
3522 fcall
->filename
.c_str(), fcall
->linenum
);
3523 int offset
= min(range
->range_left
, range
->range_right
);
3524 int width
= std::abs(range
->range_left
- range
->range_right
) + 1;
3525 varinfo_t
&v
= variables
[stmt
->children
.at(0)->str
];
3526 RTLIL::Const r
= stmt
->children
.at(1)->bitsAsConst(v
.val
.bits
.size());
3527 for (int i
= 0; i
< width
; i
++)
3528 v
.val
.bits
.at(i
+offset
-v
.offset
) = r
.bits
.at(i
);
3531 delete block
->children
.front();
3532 block
->children
.erase(block
->children
.begin());
3536 if (stmt
->type
== AST_FOR
)
3538 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(0));
3539 stmt
->children
.at(3)->children
.push_back(stmt
->children
.at(2));
3540 stmt
->children
.erase(stmt
->children
.begin() + 2);
3541 stmt
->children
.erase(stmt
->children
.begin());
3542 stmt
->type
= AST_WHILE
;
3546 if (stmt
->type
== AST_WHILE
)
3548 AstNode
*cond
= stmt
->children
.at(0)->clone();
3549 cond
->replace_variables(variables
, fcall
);
3550 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
3552 if (cond
->type
!= AST_CONSTANT
)
3553 log_file_error(stmt
->filename
, stmt
->linenum
, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
3554 fcall
->filename
.c_str(), fcall
->linenum
);
3556 if (cond
->asBool()) {
3557 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
3559 delete block
->children
.front();
3560 block
->children
.erase(block
->children
.begin());
3567 if (stmt
->type
== AST_REPEAT
)
3569 AstNode
*num
= stmt
->children
.at(0)->clone();
3570 num
->replace_variables(variables
, fcall
);
3571 while (num
->simplify(true, false, false, 1, -1, false, true)) { }
3573 if (num
->type
!= AST_CONSTANT
)
3574 log_file_error(stmt
->filename
, stmt
->linenum
, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
3575 fcall
->filename
.c_str(), fcall
->linenum
);
3577 block
->children
.erase(block
->children
.begin());
3578 for (int i
= 0; i
< num
->bitsAsConst().as_int(); i
++)
3579 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
3586 if (stmt
->type
== AST_CASE
)
3588 AstNode
*expr
= stmt
->children
.at(0)->clone();
3589 expr
->replace_variables(variables
, fcall
);
3590 while (expr
->simplify(true, false, false, 1, -1, false, true)) { }
3592 AstNode
*sel_case
= NULL
;
3593 for (size_t i
= 1; i
< stmt
->children
.size(); i
++)
3595 bool found_match
= false;
3596 log_assert(stmt
->children
.at(i
)->type
== AST_COND
|| stmt
->children
.at(i
)->type
== AST_CONDX
|| stmt
->children
.at(i
)->type
== AST_CONDZ
);
3598 if (stmt
->children
.at(i
)->children
.front()->type
== AST_DEFAULT
) {
3599 sel_case
= stmt
->children
.at(i
)->children
.back();
3603 for (size_t j
= 0; j
+1 < stmt
->children
.at(i
)->children
.size() && !found_match
; j
++)
3605 AstNode
*cond
= stmt
->children
.at(i
)->children
.at(j
)->clone();
3606 cond
->replace_variables(variables
, fcall
);
3608 cond
= new AstNode(AST_EQ
, expr
->clone(), cond
);
3609 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
3611 if (cond
->type
!= AST_CONSTANT
)
3612 log_file_error(stmt
->filename
, stmt
->linenum
, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
3613 fcall
->filename
.c_str(), fcall
->linenum
);
3615 found_match
= cond
->asBool();
3620 sel_case
= stmt
->children
.at(i
)->children
.back();
3625 block
->children
.erase(block
->children
.begin());
3627 block
->children
.insert(block
->children
.begin(), sel_case
->clone());
3633 if (stmt
->type
== AST_BLOCK
)
3635 block
->children
.erase(block
->children
.begin());
3636 block
->children
.insert(block
->children
.begin(), stmt
->children
.begin(), stmt
->children
.end());
3637 stmt
->children
.clear();
3642 log_file_error(stmt
->filename
, stmt
->linenum
, "Unsupported language construct in constant function\n%s:%d: ... called from here.\n",
3643 fcall
->filename
.c_str(), fcall
->linenum
);
3647 if (delete_temp_block
)
3650 for (auto &it
: backup_scope
)
3651 if (it
.second
== NULL
)
3652 current_scope
.erase(it
.first
);
3654 current_scope
[it
.first
] = it
.second
;
3656 return AstNode::mkconst_bits(variables
.at(str
).val
.bits
, variables
.at(str
).is_signed
);