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 for (auto &it
: node
->attributes
)
154 if (it
.first
!= ID(mem2reg
))
155 reg
->attributes
.emplace(it
.first
, it
.second
->clone());
156 reg
->filename
= node
->filename
;
157 reg
->linenum
= node
->linenum
;
158 children
.push_back(reg
);
159 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
163 AstNode
*async_block
= NULL
;
164 while (mem2reg_as_needed_pass2(mem2reg_set
, this, NULL
, async_block
)) { }
166 vector
<AstNode
*> delnodes
;
167 mem2reg_remove(mem2reg_set
, delnodes
);
169 for (auto node
: delnodes
)
173 while (simplify(const_fold
, at_zero
, in_lvalue
, 2, width_hint
, sign_hint
, in_param
)) { }
178 current_filename
= filename
;
179 set_line_num(linenum
);
181 // we do not look inside a task or function
182 // (but as soon as a task or function is instantiated we process the generated AST as usual)
183 if (type
== AST_FUNCTION
|| type
== AST_TASK
) {
188 // deactivate all calls to non-synthesis system tasks
189 // note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
190 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && (str
== "$strobe" || str
== "$monitor" || str
== "$time" ||
191 str
== "$dumpfile" || str
== "$dumpvars" || str
== "$dumpon" || str
== "$dumpoff" || str
== "$dumpall")) {
192 log_file_warning(filename
, linenum
, "Ignoring call to system %s %s.\n", type
== AST_FCALL
? "function" : "task", str
.c_str());
197 if ((type
== AST_TCALL
) && (str
== "$display" || str
== "$write") && (!current_always
|| current_always
->type
!= AST_INITIAL
)) {
198 log_file_warning(filename
, linenum
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
203 // print messages if this a call to $display() or $write()
204 // This code implements only a small subset of Verilog-2005 $display() format specifiers,
205 // but should be good enough for most uses
206 if ((type
== AST_TCALL
) && ((str
== "$display") || (str
== "$write")))
208 int nargs
= GetSize(children
);
210 log_file_error(filename
, linenum
, "System task `%s' got %d arguments, expected >= 1.\n",
211 str
.c_str(), int(children
.size()));
213 // First argument is the format string
214 AstNode
*node_string
= children
[0];
215 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
216 if (node_string
->type
!= AST_CONSTANT
)
217 log_file_error(filename
, linenum
, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str
.c_str());
218 std::string sformat
= node_string
->bitsAsConst().decode_string();
220 // Other arguments are placeholders. Process the string as we go through it
223 for (size_t i
= 0; i
< sformat
.length(); i
++)
226 if (sformat
[i
] == '%')
228 // If there's no next character, that's a problem
229 if (i
+1 >= sformat
.length())
230 log_file_error(filename
, linenum
, "System task `%s' called with `%%' at end of string.\n", str
.c_str());
232 char cformat
= sformat
[++i
];
234 // %% is special, does not need a matching argument
241 // Simplify the argument
242 AstNode
*node_arg
= nullptr;
244 // Everything from here on depends on the format specifier
253 if (next_arg
>= GetSize(children
))
254 log_file_error(filename
, linenum
, "Missing argument for %%%c format specifier in system task `%s'.\n",
255 cformat
, str
.c_str());
257 node_arg
= children
[next_arg
++];
258 while (node_arg
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
259 if (node_arg
->type
!= AST_CONSTANT
)
260 log_file_error(filename
, linenum
, "Failed to evaluate system task `%s' with non-constant argument.\n", str
.c_str());
268 log_file_error(filename
, linenum
, "System task `%s' called with invalid/unsupported format specifier.\n", str
.c_str());
276 sout
+= node_arg
->bitsAsConst().decode_string();
283 snprintf(tmp
, sizeof(tmp
), "%d", node_arg
->bitsAsConst().as_int());
292 snprintf(tmp
, sizeof(tmp
), "%x", node_arg
->bitsAsConst().as_int());
299 sout
+= log_id(current_module
->name
);
307 // not a format specifier
312 // Finally, print the message (only include a \n for $display, not for $write)
313 log("%s", sout
.c_str());
314 if (str
== "$display")
320 // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
321 if (type
== AST_WIRE
|| type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_ENUM_ITEM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_RANGE
|| type
== AST_PREFIX
|| type
== AST_TYPEDEF
)
323 if (type
== AST_IDENTIFIER
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
|| current_scope
[str
]->type
== AST_ENUM_ITEM
))
326 // in certain cases a function must be evaluated constant. this is what in_param controls.
327 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_PREFIX
)
330 std::map
<std::string
, AstNode
*> backup_scope
;
332 // create name resolution entries for all objects with names
333 // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
334 if (type
== AST_MODULE
) {
335 current_scope
.clear();
336 std::map
<std::string
, AstNode
*> this_wire_scope
;
337 for (size_t i
= 0; i
< children
.size(); i
++) {
338 AstNode
*node
= children
[i
];
340 if (node
->type
== AST_WIRE
) {
341 if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
342 for (auto c
: node
->children
[0]->children
) {
343 if (!c
->is_simple_const_expr()) {
344 if (attributes
.count("\\dynports"))
345 delete attributes
.at("\\dynports");
346 attributes
["\\dynports"] = AstNode::mkconst_int(1, true);
350 if (this_wire_scope
.count(node
->str
) > 0) {
351 AstNode
*first_node
= this_wire_scope
[node
->str
];
352 if (first_node
->is_input
&& node
->is_reg
)
353 goto wires_are_incompatible
;
354 if (!node
->is_input
&& !node
->is_output
&& node
->is_reg
&& node
->children
.size() == 0)
355 goto wires_are_compatible
;
356 if (first_node
->children
.size() == 0 && node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
357 AstNode
*r
= node
->children
[0];
358 if (r
->range_valid
&& r
->range_left
== 0 && r
->range_right
== 0) {
360 node
->children
.pop_back();
363 if (first_node
->children
.size() != node
->children
.size())
364 goto wires_are_incompatible
;
365 for (size_t j
= 0; j
< node
->children
.size(); j
++) {
366 AstNode
*n1
= first_node
->children
[j
], *n2
= node
->children
[j
];
367 if (n1
->type
== AST_RANGE
&& n2
->type
== AST_RANGE
&& n1
->range_valid
&& n2
->range_valid
) {
368 if (n1
->range_left
!= n2
->range_left
)
369 goto wires_are_incompatible
;
370 if (n1
->range_right
!= n2
->range_right
)
371 goto wires_are_incompatible
;
372 } else if (*n1
!= *n2
)
373 goto wires_are_incompatible
;
375 if (first_node
->range_left
!= node
->range_left
)
376 goto wires_are_incompatible
;
377 if (first_node
->range_right
!= node
->range_right
)
378 goto wires_are_incompatible
;
379 if (first_node
->port_id
== 0 && (node
->is_input
|| node
->is_output
))
380 goto wires_are_incompatible
;
381 wires_are_compatible
:
383 first_node
->is_input
= true;
385 first_node
->is_output
= true;
387 first_node
->is_reg
= true;
389 first_node
->is_logic
= true;
391 first_node
->is_signed
= true;
392 for (auto &it
: node
->attributes
) {
393 if (first_node
->attributes
.count(it
.first
) > 0)
394 delete first_node
->attributes
[it
.first
];
395 first_node
->attributes
[it
.first
] = it
.second
->clone();
397 children
.erase(children
.begin()+(i
--));
398 did_something
= true;
401 wires_are_incompatible
:
403 log_file_error(filename
, linenum
, "Incompatible re-declaration of wire %s.\n", node
->str
.c_str());
406 this_wire_scope
[node
->str
] = node
;
408 // these nodes appear at the top level in a module and can define names
409 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
410 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
|| node
->type
== AST_CELL
||
411 node
->type
== AST_TYPEDEF
) {
412 backup_scope
[node
->str
] = current_scope
[node
->str
];
413 current_scope
[node
->str
] = node
;
415 if (node
->type
== AST_ENUM
) {
416 current_scope
[node
->str
] = node
;
417 for (auto enode
: node
->children
) {
418 log_assert(enode
->type
==AST_ENUM_ITEM
);
419 if (current_scope
.count(enode
->str
) == 0) {
420 current_scope
[enode
->str
] = enode
;
425 for (size_t i
= 0; i
< children
.size(); i
++) {
426 AstNode
*node
= children
[i
];
427 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_MEMORY
|| node
->type
== AST_TYPEDEF
)
428 while (node
->simplify(true, false, false, 1, -1, false, node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
))
429 did_something
= true;
430 if (node
->type
== AST_ENUM
) {
431 for (auto enode
: node
->children
){
432 log_assert(enode
->type
==AST_ENUM_ITEM
);
433 while (node
->simplify(true, false, false, 1, -1, false, in_param
))
434 did_something
= true;
440 auto backup_current_block
= current_block
;
441 auto backup_current_block_child
= current_block_child
;
442 auto backup_current_top_block
= current_top_block
;
443 auto backup_current_always
= current_always
;
444 auto backup_current_always_clocked
= current_always_clocked
;
446 if (type
== AST_ALWAYS
|| type
== AST_INITIAL
)
448 if (current_always
!= nullptr)
449 log_file_error(filename
, linenum
, "Invalid nesting of always blocks and/or initializations.\n");
451 current_always
= this;
452 current_always_clocked
= false;
454 if (type
== AST_ALWAYS
)
455 for (auto child
: children
) {
456 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
457 current_always_clocked
= true;
458 if (child
->type
== AST_EDGE
&& GetSize(child
->children
) == 1 &&
459 child
->children
[0]->type
== AST_IDENTIFIER
&& child
->children
[0]->str
== "\\$global_clock")
460 current_always_clocked
= true;
464 int backup_width_hint
= width_hint
;
465 bool backup_sign_hint
= sign_hint
;
467 bool detect_width_simple
= false;
468 bool child_0_is_self_determined
= false;
469 bool child_1_is_self_determined
= false;
470 bool child_2_is_self_determined
= false;
471 bool children_are_self_determined
= false;
472 bool reset_width_after_children
= false;
479 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, true, stage
, -1, false, in_param
) == true)
480 did_something
= true;
481 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
) == true)
482 did_something
= true;
483 children
[0]->detectSignWidth(backup_width_hint
, backup_sign_hint
);
484 children
[1]->detectSignWidth(width_hint
, sign_hint
);
485 width_hint
= max(width_hint
, backup_width_hint
);
486 child_0_is_self_determined
= true;
487 // test only once, before optimizations and memory mappings but after assignment LHS was mapped to an identifier
488 if (children
[0]->id2ast
&& !children
[0]->was_checked
) {
489 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->id2ast
->is_logic
)
490 children
[0]->id2ast
->is_reg
= true; // if logic type is used in a block asignment
491 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && !children
[0]->id2ast
->is_reg
)
492 log_warning("wire '%s' is assigned in a block at %s:%d.\n", children
[0]->str
.c_str(), filename
.c_str(), linenum
);
493 if (type
== AST_ASSIGN
&& children
[0]->id2ast
->is_reg
) {
494 bool is_rand_reg
= false;
495 if (children
[1]->type
== AST_FCALL
) {
496 if (children
[1]->str
== "\\$anyconst")
498 if (children
[1]->str
== "\\$anyseq")
500 if (children
[1]->str
== "\\$allconst")
502 if (children
[1]->str
== "\\$allseq")
506 log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children
[0]->str
.c_str(), filename
.c_str(), linenum
);
508 children
[0]->was_checked
= true;
513 //log("\nENUM %s: %d child %d\n", str.c_str(), basic_prep, children[0]->basic_prep);
515 for (auto item_node
: children
) {
516 while (!item_node
->basic_prep
&& item_node
->simplify(false, false, false, stage
, -1, false, in_param
))
517 did_something
= true;
519 // allocate values (called more than once)
520 allocateDefaultEnumValues();
526 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, true) == true)
527 did_something
= true;
528 children
[0]->detectSignWidth(width_hint
, sign_hint
);
529 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
530 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, true) == true)
531 did_something
= true;
532 if (!children
[1]->range_valid
)
533 log_file_error(filename
, linenum
, "Non-constant width range on parameter decl.\n");
534 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
538 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, in_param
))
539 did_something
= true;
540 children
[0]->detectSignWidth(width_hint
, sign_hint
);
541 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
542 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
))
543 did_something
= true;
544 if (!children
[1]->range_valid
)
545 log_file_error(filename
, linenum
, "Non-constant width range on enum item decl.\n");
546 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
552 case AST_TO_UNSIGNED
:
558 case AST_REDUCE_XNOR
:
559 case AST_REDUCE_BOOL
:
560 detect_width_simple
= true;
561 children_are_self_determined
= true;
576 detect_width_simple
= true;
580 case AST_SHIFT_RIGHT
:
581 case AST_SHIFT_SLEFT
:
582 case AST_SHIFT_SRIGHT
:
584 detect_width_simple
= true;
585 child_1_is_self_determined
= true;
598 for (auto child
: children
) {
599 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
600 did_something
= true;
601 child
->detectSignWidthWorker(width_hint
, sign_hint
);
603 reset_width_after_children
= true;
609 detect_width_simple
= true;
610 children_are_self_determined
= true;
614 detect_width_simple
= true;
615 child_0_is_self_determined
= true;
619 detect_width_simple
= true;
620 children_are_self_determined
= true;
625 children_are_self_determined
= true;
633 if (detect_width_simple
&& width_hint
< 0) {
634 if (type
== AST_REPLICATE
)
635 while (children
[0]->simplify(true, false, in_lvalue
, stage
, -1, false, true) == true)
636 did_something
= true;
637 for (auto child
: children
)
638 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
639 did_something
= true;
640 detectSignWidth(width_hint
, sign_hint
);
643 if (type
== AST_FCALL
&& str
== "\\$past")
644 detectSignWidth(width_hint
, sign_hint
);
646 if (type
== AST_TERNARY
) {
647 int width_hint_left
, width_hint_right
;
648 bool sign_hint_left
, sign_hint_right
;
649 bool found_real_left
, found_real_right
;
650 children
[1]->detectSignWidth(width_hint_left
, sign_hint_left
, &found_real_left
);
651 children
[2]->detectSignWidth(width_hint_right
, sign_hint_right
, &found_real_right
);
652 if (found_real_left
|| found_real_right
) {
653 child_1_is_self_determined
= true;
654 child_2_is_self_determined
= true;
658 if (type
== AST_CONDX
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
659 for (auto &bit
: children
.at(0)->bits
)
660 if (bit
== State::Sz
|| bit
== State::Sx
)
664 if (type
== AST_CONDZ
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
665 for (auto &bit
: children
.at(0)->bits
)
666 if (bit
== State::Sz
)
670 if (const_fold
&& type
== AST_CASE
)
672 while (children
[0]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
673 if (children
[0]->type
== AST_CONSTANT
&& children
[0]->bits_only_01()) {
674 std::vector
<AstNode
*> new_children
;
675 new_children
.push_back(children
[0]);
676 for (int i
= 1; i
< GetSize(children
); i
++) {
677 AstNode
*child
= children
[i
];
678 log_assert(child
->type
== AST_COND
|| child
->type
== AST_CONDX
|| child
->type
== AST_CONDZ
);
679 for (auto v
: child
->children
) {
680 if (v
->type
== AST_DEFAULT
)
681 goto keep_const_cond
;
682 if (v
->type
== AST_BLOCK
)
684 while (v
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
685 if (v
->type
== AST_CONSTANT
&& v
->bits_only_01()) {
686 if (v
->bits
== children
[0]->bits
) {
687 while (i
+1 < GetSize(children
))
688 delete children
[++i
];
689 goto keep_const_cond
;
693 goto keep_const_cond
;
697 new_children
.push_back(child
);
701 new_children
.swap(children
);
705 // simplify all children first
706 // (iterate by index as e.g. auto wires can add new children in the process)
707 for (size_t i
= 0; i
< children
.size(); i
++) {
708 bool did_something_here
= true;
709 bool backup_flag_autowire
= flag_autowire
;
710 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && i
>= 3)
712 if ((type
== AST_GENIF
|| type
== AST_GENCASE
) && i
>= 1)
714 if (type
== AST_GENBLOCK
)
716 if (type
== AST_BLOCK
&& !str
.empty())
718 if (type
== AST_PREFIX
&& i
>= 1)
720 if (type
== AST_DEFPARAM
&& i
== 0)
721 flag_autowire
= true;
722 while (did_something_here
&& i
< children
.size()) {
723 bool const_fold_here
= const_fold
, in_lvalue_here
= in_lvalue
;
724 int width_hint_here
= width_hint
;
725 bool sign_hint_here
= sign_hint
;
726 bool in_param_here
= in_param
;
727 if (i
== 0 && (type
== AST_REPLICATE
|| type
== AST_WIRE
))
728 const_fold_here
= true, in_param_here
= true;
729 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
)
730 const_fold_here
= true;
731 if (i
== 0 && (type
== AST_ASSIGN
|| type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
))
732 in_lvalue_here
= true;
733 if (type
== AST_BLOCK
) {
734 current_block
= this;
735 current_block_child
= children
[i
];
737 if ((type
== AST_ALWAYS
|| type
== AST_INITIAL
) && children
[i
]->type
== AST_BLOCK
)
738 current_top_block
= children
[i
];
739 if (i
== 0 && child_0_is_self_determined
)
740 width_hint_here
= -1, sign_hint_here
= false;
741 if (i
== 1 && child_1_is_self_determined
)
742 width_hint_here
= -1, sign_hint_here
= false;
743 if (i
== 2 && child_2_is_self_determined
)
744 width_hint_here
= -1, sign_hint_here
= false;
745 if (children_are_self_determined
)
746 width_hint_here
= -1, sign_hint_here
= false;
747 did_something_here
= children
[i
]->simplify(const_fold_here
, at_zero
, in_lvalue_here
, stage
, width_hint_here
, sign_hint_here
, in_param_here
);
748 if (did_something_here
)
749 did_something
= true;
751 if (stage
== 2 && children
[i
]->type
== AST_INITIAL
&& current_ast_mod
!= this) {
752 current_ast_mod
->children
.push_back(children
[i
]);
753 children
.erase(children
.begin() + (i
--));
754 did_something
= true;
756 flag_autowire
= backup_flag_autowire
;
758 for (auto &attr
: attributes
) {
759 while (attr
.second
->simplify(true, false, false, stage
, -1, false, true))
760 did_something
= true;
763 if (reset_width_after_children
) {
764 width_hint
= backup_width_hint
;
765 sign_hint
= backup_sign_hint
;
767 detectSignWidth(width_hint
, sign_hint
);
770 current_block
= backup_current_block
;
771 current_block_child
= backup_current_block_child
;
772 current_top_block
= backup_current_top_block
;
773 current_always
= backup_current_always
;
774 current_always_clocked
= backup_current_always_clocked
;
776 for (auto it
= backup_scope
.begin(); it
!= backup_scope
.end(); it
++) {
777 if (it
->second
== NULL
)
778 current_scope
.erase(it
->first
);
780 current_scope
[it
->first
] = it
->second
;
783 current_filename
= filename
;
784 set_line_num(linenum
);
786 if (type
== AST_MODULE
)
787 current_scope
.clear();
789 // convert defparam nodes to cell parameters
790 if (type
== AST_DEFPARAM
&& !children
.empty())
792 if (children
[0]->type
!= AST_IDENTIFIER
)
793 log_file_error(filename
, linenum
, "Module name in defparam contains non-constant expressions!\n");
795 string modname
, paramname
= children
[0]->str
;
797 size_t pos
= paramname
.rfind('.');
799 while (pos
!= 0 && pos
!= std::string::npos
)
801 modname
= paramname
.substr(0, pos
);
803 if (current_scope
.count(modname
))
806 pos
= paramname
.rfind('.', pos
- 1);
809 if (pos
== std::string::npos
)
810 log_file_error(filename
, linenum
, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname
).c_str());
812 paramname
= "\\" + paramname
.substr(pos
+1);
814 if (current_scope
.at(modname
)->type
!= AST_CELL
)
815 log_file_error(filename
, linenum
, "Defparam argument `%s . %s` does not match a cell!\n",
816 RTLIL::unescape_id(modname
).c_str(), RTLIL::unescape_id(paramname
).c_str());
818 AstNode
*paraset
= new AstNode(AST_PARASET
, children
[1]->clone(), GetSize(children
) > 2 ? children
[2]->clone() : NULL
);
819 paraset
->str
= paramname
;
821 AstNode
*cell
= current_scope
.at(modname
);
822 cell
->children
.insert(cell
->children
.begin() + 1, paraset
);
827 if (type
== AST_TYPEDEF
) {
828 log_assert(children
.size() == 1);
829 log_assert(children
[0]->type
== AST_WIRE
|| children
[0]->type
== AST_MEMORY
);
830 while(children
[0]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
))
831 did_something
= true;
832 log_assert(!children
[0]->is_custom_type
);
835 // resolve types of wires
836 if (type
== AST_WIRE
|| type
== AST_MEMORY
) {
837 if (is_custom_type
) {
838 log_assert(children
.size() >= 1);
839 log_assert(children
[0]->type
== AST_WIRETYPE
);
840 if (!current_scope
.count(children
[0]->str
))
841 log_file_error(filename
, linenum
, "Unknown identifier `%s' used as type name\n", children
[0]->str
.c_str());
842 AstNode
*resolved_type
= current_scope
.at(children
[0]->str
);
843 if (resolved_type
->type
!= AST_TYPEDEF
)
844 log_file_error(filename
, linenum
, "`%s' does not name a type\n", children
[0]->str
.c_str());
845 log_assert(resolved_type
->children
.size() == 1);
846 AstNode
*templ
= resolved_type
->children
[0];
847 // Remove type reference
849 children
.erase(children
.begin());
851 // Ensure typedef itself is fully simplified
852 while(templ
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
854 if (type
== AST_WIRE
)
856 is_reg
= templ
->is_reg
;
857 is_logic
= templ
->is_logic
;
858 is_signed
= templ
->is_signed
;
859 is_string
= templ
->is_string
;
860 is_custom_type
= templ
->is_custom_type
;
862 range_valid
= templ
->range_valid
;
863 range_swapped
= templ
->range_swapped
;
864 range_left
= templ
->range_left
;
865 range_right
= templ
->range_right
;
866 attributes
["\\wiretype"] = mkconst_str(resolved_type
->str
);
868 if (templ
->attributes
.count("\\enum_type")){
869 //get reference to enum node:
870 std::string enum_type
= templ
->attributes
["\\enum_type"]->str
.c_str();
871 // log("enum_type=%s (count=%lu)\n", enum_type.c_str(), current_scope.count(enum_type));
872 // log("current scope:\n");
873 // for (auto &it : current_scope)
874 // log(" %s\n", it.first.c_str());
875 log_assert(current_scope
.count(enum_type
) == 1);
876 AstNode
*enum_node
= current_scope
.at(enum_type
);
877 log_assert(enum_node
->type
== AST_ENUM
);
878 //get width from 1st enum item:
879 log_assert(enum_node
->children
.size() >= 1);
880 AstNode
*enum_item0
= enum_node
->children
[0];
881 log_assert(enum_item0
->type
== AST_ENUM_ITEM
);
883 if (!enum_item0
->range_valid
)
885 else if (enum_item0
->range_swapped
)
886 width
= enum_item0
->range_right
- enum_item0
->range_left
+ 1;
888 width
= enum_item0
->range_left
- enum_item0
->range_right
+ 1;
889 log_assert(width
> 0);
890 //add declared enum items:
891 for (auto enum_item
: enum_node
->children
){
892 log_assert(enum_item
->type
== AST_ENUM_ITEM
);
895 if (enum_item
->children
.size() == 1){
897 } else if (enum_item
->children
.size() == 2){
898 log_assert(enum_item
->children
[1]->type
== AST_RANGE
);
899 is_signed
= enum_item
->children
[1]->is_signed
;
901 log_error("enum_item children size==%lu, expected 1 or 2 for %s (%s)\n",
902 enum_item
->children
.size(),
903 enum_item
->str
.c_str(), enum_node
->str
.c_str()
906 //start building attribute string
907 std::string enum_item_str
= "\\enum_";
908 enum_item_str
.append(std::to_string(width
));
909 enum_item_str
.append("_");
910 //get enum item value
911 if(enum_item
->children
[0]->type
!= AST_CONSTANT
){
912 log_error("expected const, got %s for %s (%s)\n",
913 type2str(enum_item
->children
[0]->type
).c_str(),
914 enum_item
->str
.c_str(), enum_node
->str
.c_str()
917 int val
= enum_item
->children
[0]->asInt(is_signed
);
918 enum_item_str
.append(std::to_string(val
));
919 //set attribute for available val to enum item name mappings
920 attributes
[enum_item_str
.c_str()] = mkconst_str(enum_item
->str
);
924 // Insert clones children from template at beginning
925 for (int i
= 0; i
< GetSize(templ
->children
); i
++)
926 children
.insert(children
.begin() + i
, templ
->children
[i
]->clone());
928 if (type
== AST_MEMORY
&& GetSize(children
) == 1) {
929 // Single-bit memories must have [0:0] range
930 AstNode
*rng
= new AstNode(AST_RANGE
);
931 rng
->children
.push_back(AstNode::mkconst_int(0, true));
932 rng
->children
.push_back(AstNode::mkconst_int(0, true));
933 children
.insert(children
.begin(), rng
);
936 did_something
= true;
938 log_assert(!is_custom_type
);
941 // resolve types of parameters
942 if (type
== AST_LOCALPARAM
|| type
== AST_PARAMETER
) {
943 if (is_custom_type
) {
944 log_assert(children
.size() == 2);
945 log_assert(children
[1]->type
== AST_WIRETYPE
);
946 if (!current_scope
.count(children
[1]->str
))
947 log_file_error(filename
, linenum
, "Unknown identifier `%s' used as type name\n", children
[1]->str
.c_str());
948 AstNode
*resolved_type
= current_scope
.at(children
[1]->str
);
949 if (resolved_type
->type
!= AST_TYPEDEF
)
950 log_file_error(filename
, linenum
, "`%s' does not name a type\n", children
[1]->str
.c_str());
951 log_assert(resolved_type
->children
.size() == 1);
952 AstNode
*templ
= resolved_type
->children
[0];
956 // Ensure typedef itself is fully simplified
957 while(templ
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
959 if (templ
->type
== AST_MEMORY
)
960 log_file_error(filename
, linenum
, "unpacked array type `%s' cannot be used for a parameter\n", children
[1]->str
.c_str());
961 is_signed
= templ
->is_signed
;
962 is_string
= templ
->is_string
;
963 is_custom_type
= templ
->is_custom_type
;
965 range_valid
= templ
->range_valid
;
966 range_swapped
= templ
->range_swapped
;
967 range_left
= templ
->range_left
;
968 range_right
= templ
->range_right
;
969 attributes
["\\wiretype"] = mkconst_str(resolved_type
->str
);
970 for (auto template_child
: templ
->children
)
971 children
.push_back(template_child
->clone());
972 did_something
= true;
974 log_assert(!is_custom_type
);
977 // resolve constant prefixes
978 if (type
== AST_PREFIX
) {
979 if (children
[0]->type
!= AST_CONSTANT
) {
980 // dumpAst(NULL, "> ");
981 log_file_error(filename
, linenum
, "Index in generate block prefix syntax is not constant!\n");
983 if (children
[1]->type
== AST_PREFIX
)
984 children
[1]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
);
985 log_assert(children
[1]->type
== AST_IDENTIFIER
);
986 newNode
= children
[1]->clone();
987 const char *second_part
= children
[1]->str
.c_str();
988 if (second_part
[0] == '\\')
990 newNode
->str
= stringf("%s[%d].%s", str
.c_str(), children
[0]->integer
, second_part
);
994 // evaluate TO_BITS nodes
995 if (type
== AST_TO_BITS
) {
996 if (children
[0]->type
!= AST_CONSTANT
)
997 log_file_error(filename
, linenum
, "Left operand of to_bits expression is not constant!\n");
998 if (children
[1]->type
!= AST_CONSTANT
)
999 log_file_error(filename
, linenum
, "Right operand of to_bits expression is not constant!\n");
1000 RTLIL::Const new_value
= children
[1]->bitsAsConst(children
[0]->bitsAsConst().as_int(), children
[1]->is_signed
);
1001 newNode
= mkconst_bits(new_value
.bits
, children
[1]->is_signed
);
1005 // annotate constant ranges
1006 if (type
== AST_RANGE
) {
1007 bool old_range_valid
= range_valid
;
1008 range_valid
= false;
1009 range_swapped
= false;
1012 log_assert(children
.size() >= 1);
1013 if (children
[0]->type
== AST_CONSTANT
) {
1015 range_left
= children
[0]->integer
;
1016 if (children
.size() == 1)
1017 range_right
= range_left
;
1019 if (children
.size() >= 2) {
1020 if (children
[1]->type
== AST_CONSTANT
)
1021 range_right
= children
[1]->integer
;
1023 range_valid
= false;
1025 if (old_range_valid
!= range_valid
)
1026 did_something
= true;
1027 if (range_valid
&& range_left
>= 0 && range_right
> range_left
) {
1028 int tmp
= range_right
;
1029 range_right
= range_left
;
1031 range_swapped
= true;
1035 // annotate wires with their ranges
1036 if (type
== AST_WIRE
) {
1037 if (children
.size() > 0) {
1038 if (children
[0]->range_valid
) {
1040 did_something
= true;
1042 range_swapped
= children
[0]->range_swapped
;
1043 range_left
= children
[0]->range_left
;
1044 range_right
= children
[0]->range_right
;
1048 did_something
= true;
1050 range_swapped
= false;
1056 // resolve multiranges on memory decl
1057 if (type
== AST_MEMORY
&& children
.size() > 1 && children
[1]->type
== AST_MULTIRANGE
)
1060 multirange_dimensions
.clear();
1061 for (auto range
: children
[1]->children
) {
1062 if (!range
->range_valid
)
1063 log_file_error(filename
, linenum
, "Non-constant range on memory decl.\n");
1064 multirange_dimensions
.push_back(min(range
->range_left
, range
->range_right
));
1065 multirange_dimensions
.push_back(max(range
->range_left
, range
->range_right
) - min(range
->range_left
, range
->range_right
) + 1);
1066 total_size
*= multirange_dimensions
.back();
1069 children
[1] = new AstNode(AST_RANGE
, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size
-1, true));
1070 did_something
= true;
1073 // resolve multiranges on memory access
1074 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
&& children
.size() > 0 && children
[0]->type
== AST_MULTIRANGE
)
1076 AstNode
*index_expr
= nullptr;
1078 for (int i
= 0; 2*i
< GetSize(id2ast
->multirange_dimensions
); i
++)
1080 if (GetSize(children
[0]->children
) < i
)
1081 log_file_error(filename
, linenum
, "Insufficient number of array indices for %s.\n", log_id(str
));
1083 AstNode
*new_index_expr
= children
[0]->children
[i
]->children
.at(0)->clone();
1085 if (id2ast
->multirange_dimensions
[2*i
])
1086 new_index_expr
= new AstNode(AST_SUB
, new_index_expr
, AstNode::mkconst_int(id2ast
->multirange_dimensions
[2*i
], true));
1089 index_expr
= new_index_expr
;
1091 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
);
1094 for (int i
= GetSize(id2ast
->multirange_dimensions
)/2; i
< GetSize(children
[0]->children
); i
++)
1095 children
.push_back(children
[0]->children
[i
]->clone());
1098 if (index_expr
== nullptr)
1099 children
.erase(children
.begin());
1101 children
[0] = new AstNode(AST_RANGE
, index_expr
);
1103 did_something
= true;
1106 // trim/extend parameters
1107 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_ENUM_ITEM
) {
1108 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
1109 if (!children
[1]->range_valid
)
1110 log_file_error(filename
, linenum
, "Non-constant width range on parameter decl.\n");
1111 int width
= std::abs(children
[1]->range_left
- children
[1]->range_right
) + 1;
1112 if (children
[0]->type
== AST_REALVALUE
) {
1113 RTLIL::Const constvalue
= children
[0]->realAsConst(width
);
1114 log_file_warning(filename
, linenum
, "converting real value %e to binary %s.\n",
1115 children
[0]->realvalue
, log_signal(constvalue
));
1117 children
[0] = mkconst_bits(constvalue
.bits
, sign_hint
);
1118 did_something
= true;
1120 if (children
[0]->type
== AST_CONSTANT
) {
1121 if (width
!= int(children
[0]->bits
.size())) {
1122 RTLIL::SigSpec
sig(children
[0]->bits
);
1123 sig
.extend_u0(width
, children
[0]->is_signed
);
1124 AstNode
*old_child_0
= children
[0];
1125 children
[0] = mkconst_bits(sig
.as_const().bits
, is_signed
);
1128 children
[0]->is_signed
= is_signed
;
1131 range_swapped
= children
[1]->range_swapped
;
1132 range_left
= children
[1]->range_left
;
1133 range_right
= children
[1]->range_right
;
1135 if (children
.size() > 1 && children
[1]->type
== AST_REALVALUE
&& children
[0]->type
== AST_CONSTANT
) {
1136 double as_realvalue
= children
[0]->asReal(sign_hint
);
1138 children
[0] = new AstNode(AST_REALVALUE
);
1139 children
[0]->realvalue
= as_realvalue
;
1140 did_something
= true;
1144 // annotate identifiers using scope resolution and create auto-wires as needed
1145 if (type
== AST_IDENTIFIER
) {
1146 if (current_scope
.count(str
) == 0) {
1147 for (auto node
: current_ast_mod
->children
) {
1148 //log("looking at mod scope child %s\n", type2str(node->type).c_str());
1149 switch (node
->type
) {
1151 case AST_LOCALPARAM
:
1158 case AST_DPI_FUNCTION
:
1159 //log("found child %s, %s\n", type2str(node->type).c_str(), node->str.c_str());
1160 if (str
== node
->str
) {
1161 log("add %s, type %s to scope\n", str
.c_str(), type2str(node
->type
).c_str());
1162 current_scope
[node
->str
] = node
;
1166 current_scope
[node
->str
] = node
;
1167 for (auto enum_node
: node
->children
) {
1168 log_assert(enum_node
->type
==AST_ENUM_ITEM
);
1169 if (str
== enum_node
->str
) {
1170 //log("\nadding enum item %s to scope\n", str.c_str());
1171 current_scope
[str
] = enum_node
;
1180 if (current_scope
.count(str
) == 0) {
1181 if (flag_autowire
|| str
== "\\$global_clock") {
1182 AstNode
*auto_wire
= new AstNode(AST_AUTOWIRE
);
1183 auto_wire
->str
= str
;
1184 current_ast_mod
->children
.push_back(auto_wire
);
1185 current_scope
[str
] = auto_wire
;
1186 did_something
= true;
1188 log_file_error(filename
, linenum
, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str
.c_str());
1191 if (id2ast
!= current_scope
[str
]) {
1192 id2ast
= current_scope
[str
];
1193 did_something
= true;
1197 // split memory access with bit select to individual statements
1198 if (type
== AST_IDENTIFIER
&& children
.size() == 2 && children
[0]->type
== AST_RANGE
&& children
[1]->type
== AST_RANGE
&& !in_lvalue
)
1200 if (id2ast
== NULL
|| id2ast
->type
!= AST_MEMORY
|| children
[0]->children
.size() != 1)
1201 log_file_error(filename
, linenum
, "Invalid bit-select on memory access!\n");
1203 int mem_width
, mem_size
, addr_bits
;
1204 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
1206 int data_range_left
= id2ast
->children
[0]->range_left
;
1207 int data_range_right
= id2ast
->children
[0]->range_right
;
1209 if (id2ast
->children
[0]->range_swapped
)
1210 std::swap(data_range_left
, data_range_right
);
1212 std::stringstream sstr
;
1213 sstr
<< "$mem2bits$" << str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1214 std::string wire_id
= sstr
.str();
1216 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
1217 wire
->str
= wire_id
;
1219 wire
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
1220 current_ast_mod
->children
.push_back(wire
);
1221 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
1223 AstNode
*data
= clone();
1224 delete data
->children
[1];
1225 data
->children
.pop_back();
1227 AstNode
*assign
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), data
);
1228 assign
->children
[0]->str
= wire_id
;
1229 assign
->children
[0]->was_checked
= true;
1233 size_t assign_idx
= 0;
1234 while (assign_idx
< current_block
->children
.size() && current_block
->children
[assign_idx
] != current_block_child
)
1236 log_assert(assign_idx
< current_block
->children
.size());
1237 current_block
->children
.insert(current_block
->children
.begin()+assign_idx
, assign
);
1238 wire
->is_reg
= true;
1242 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
1243 proc
->children
[0]->children
.push_back(assign
);
1244 current_ast_mod
->children
.push_back(proc
);
1247 newNode
= new AstNode(AST_IDENTIFIER
, children
[1]->clone());
1248 newNode
->str
= wire_id
;
1249 newNode
->id2ast
= wire
;
1253 if (type
== AST_WHILE
)
1254 log_file_error(filename
, linenum
, "While loops are only allowed in constant functions!\n");
1256 if (type
== AST_REPEAT
)
1258 AstNode
*count
= children
[0];
1259 AstNode
*body
= children
[1];
1261 // eval count expression
1262 while (count
->simplify(true, false, false, stage
, 32, true, false)) { }
1264 if (count
->type
!= AST_CONSTANT
)
1265 log_file_error(filename
, linenum
, "Repeat loops outside must have constant repeat counts!\n");
1267 // convert to a block with the body repeated n times
1270 for (int i
= 0; i
< count
->bitsAsConst().as_int(); i
++)
1271 children
.insert(children
.begin(), body
->clone());
1275 did_something
= true;
1278 // unroll for loops and generate-for blocks
1279 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && children
.size() != 0)
1281 AstNode
*init_ast
= children
[0];
1282 AstNode
*while_ast
= children
[1];
1283 AstNode
*next_ast
= children
[2];
1284 AstNode
*body_ast
= children
[3];
1286 while (body_ast
->type
== AST_GENBLOCK
&& body_ast
->str
.empty() &&
1287 body_ast
->children
.size() == 1 && body_ast
->children
.at(0)->type
== AST_GENBLOCK
)
1288 body_ast
= body_ast
->children
.at(0);
1290 if (init_ast
->type
!= AST_ASSIGN_EQ
)
1291 log_file_error(filename
, linenum
, "Unsupported 1st expression of generate for-loop!\n");
1292 if (next_ast
->type
!= AST_ASSIGN_EQ
)
1293 log_file_error(filename
, linenum
, "Unsupported 3rd expression of generate for-loop!\n");
1295 if (type
== AST_GENFOR
) {
1296 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
1297 log_file_error(filename
, linenum
, "Left hand side of 1st expression of generate for-loop is not a gen var!\n");
1298 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
1299 log_file_error(filename
, linenum
, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n");
1301 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1302 log_file_error(filename
, linenum
, "Left hand side of 1st expression of generate for-loop is not a register!\n");
1303 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1304 log_file_error(filename
, linenum
, "Left hand side of 3rd expression of generate for-loop is not a register!\n");
1307 if (init_ast
->children
[0]->id2ast
!= next_ast
->children
[0]->id2ast
)
1308 log_file_error(filename
, linenum
, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n");
1310 // eval 1st expression
1311 AstNode
*varbuf
= init_ast
->children
[1]->clone();
1313 int expr_width_hint
= -1;
1314 bool expr_sign_hint
= true;
1315 varbuf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1316 while (varbuf
->simplify(true, false, false, stage
, 32, true, false)) { }
1319 if (varbuf
->type
!= AST_CONSTANT
)
1320 log_file_error(filename
, linenum
, "Right hand side of 1st expression of generate for-loop is not constant!\n");
1322 varbuf
= new AstNode(AST_LOCALPARAM
, varbuf
);
1323 varbuf
->str
= init_ast
->children
[0]->str
;
1325 auto resolved
= current_scope
.at(init_ast
->children
[0]->str
);
1326 if (resolved
->range_valid
) {
1327 varbuf
->range_left
= resolved
->range_left
;
1328 varbuf
->range_right
= resolved
->range_right
;
1329 varbuf
->range_swapped
= resolved
->range_swapped
;
1330 varbuf
->range_valid
= resolved
->range_valid
;
1333 AstNode
*backup_scope_varbuf
= current_scope
[varbuf
->str
];
1334 current_scope
[varbuf
->str
] = varbuf
;
1336 size_t current_block_idx
= 0;
1337 if (type
== AST_FOR
) {
1338 while (current_block_idx
< current_block
->children
.size() &&
1339 current_block
->children
[current_block_idx
] != current_block_child
)
1340 current_block_idx
++;
1345 // eval 2nd expression
1346 AstNode
*buf
= while_ast
->clone();
1348 int expr_width_hint
= -1;
1349 bool expr_sign_hint
= true;
1350 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1351 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, false)) { }
1354 if (buf
->type
!= AST_CONSTANT
)
1355 log_file_error(filename
, linenum
, "2nd expression of generate for-loop is not constant!\n");
1357 if (buf
->integer
== 0) {
1364 int index
= varbuf
->children
[0]->integer
;
1365 if (body_ast
->type
== AST_GENBLOCK
)
1366 buf
= body_ast
->clone();
1368 buf
= new AstNode(AST_GENBLOCK
, body_ast
->clone());
1369 if (buf
->str
.empty()) {
1370 std::stringstream sstr
;
1371 sstr
<< "$genblock$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1372 buf
->str
= sstr
.str();
1374 std::map
<std::string
, std::string
> name_map
;
1375 std::stringstream sstr
;
1376 sstr
<< buf
->str
<< "[" << index
<< "].";
1377 buf
->expand_genblock(varbuf
->str
, sstr
.str(), name_map
);
1379 if (type
== AST_GENFOR
) {
1380 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1381 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1382 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1385 for (size_t i
= 0; i
< buf
->children
.size(); i
++)
1386 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
->children
[i
]);
1388 buf
->children
.clear();
1391 // eval 3rd expression
1392 buf
= next_ast
->children
[1]->clone();
1394 int expr_width_hint
= -1;
1395 bool expr_sign_hint
= true;
1396 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1397 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, true)) { }
1400 if (buf
->type
!= AST_CONSTANT
)
1401 log_file_error(filename
, linenum
, "Right hand side of 3rd expression of generate for-loop is not constant (%s)!\n", type2str(buf
->type
).c_str());
1403 delete varbuf
->children
[0];
1404 varbuf
->children
[0] = buf
;
1407 if (type
== AST_FOR
) {
1408 AstNode
*buf
= next_ast
->clone();
1409 delete buf
->children
[1];
1410 buf
->children
[1] = varbuf
->children
[0]->clone();
1411 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
);
1414 current_scope
[varbuf
->str
] = backup_scope_varbuf
;
1417 did_something
= true;
1420 // check for local objects in unnamed block
1421 if (type
== AST_BLOCK
&& str
.empty())
1423 for (size_t i
= 0; i
< children
.size(); i
++)
1424 if (children
[i
]->type
== AST_WIRE
|| children
[i
]->type
== AST_MEMORY
|| children
[i
]->type
== AST_PARAMETER
|| children
[i
]->type
== AST_LOCALPARAM
|| children
[i
]->type
== AST_TYPEDEF
)
1425 log_file_error(children
[i
]->filename
, children
[i
]->linenum
, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
1428 // transform block with name
1429 if (type
== AST_BLOCK
&& !str
.empty())
1431 std::map
<std::string
, std::string
> name_map
;
1432 expand_genblock(std::string(), str
+ ".", name_map
);
1434 std::vector
<AstNode
*> new_children
;
1435 for (size_t i
= 0; i
< children
.size(); i
++)
1436 if (children
[i
]->type
== AST_WIRE
|| children
[i
]->type
== AST_MEMORY
|| children
[i
]->type
== AST_PARAMETER
|| children
[i
]->type
== AST_LOCALPARAM
|| children
[i
]->type
== AST_TYPEDEF
) {
1437 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1438 current_ast_mod
->children
.push_back(children
[i
]);
1439 current_scope
[children
[i
]->str
] = children
[i
];
1441 new_children
.push_back(children
[i
]);
1443 children
.swap(new_children
);
1444 did_something
= true;
1448 // simplify unconditional generate block
1449 if (type
== AST_GENBLOCK
&& children
.size() != 0)
1452 std::map
<std::string
, std::string
> name_map
;
1453 expand_genblock(std::string(), str
+ ".", name_map
);
1456 for (size_t i
= 0; i
< children
.size(); i
++) {
1457 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1458 current_ast_mod
->children
.push_back(children
[i
]);
1462 did_something
= true;
1465 // simplify generate-if blocks
1466 if (type
== AST_GENIF
&& children
.size() != 0)
1468 AstNode
*buf
= children
[0]->clone();
1469 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1470 if (buf
->type
!= AST_CONSTANT
) {
1471 // for (auto f : log_files)
1472 // dumpAst(f, "verilog-ast> ");
1473 log_file_error(filename
, linenum
, "Condition for generate if is not constant!\n");
1475 if (buf
->asBool() != 0) {
1477 buf
= children
[1]->clone();
1480 buf
= children
.size() > 2 ? children
[2]->clone() : NULL
;
1485 if (buf
->type
!= AST_GENBLOCK
)
1486 buf
= new AstNode(AST_GENBLOCK
, buf
);
1488 if (!buf
->str
.empty()) {
1489 std::map
<std::string
, std::string
> name_map
;
1490 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1493 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1494 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1495 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1498 buf
->children
.clear();
1503 did_something
= true;
1506 // simplify generate-case blocks
1507 if (type
== AST_GENCASE
&& children
.size() != 0)
1509 AstNode
*buf
= children
[0]->clone();
1510 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1511 if (buf
->type
!= AST_CONSTANT
) {
1512 // for (auto f : log_files)
1513 // dumpAst(f, "verilog-ast> ");
1514 log_file_error(filename
, linenum
, "Condition for generate case is not constant!\n");
1517 bool ref_signed
= buf
->is_signed
;
1518 RTLIL::Const ref_value
= buf
->bitsAsConst();
1521 AstNode
*selected_case
= NULL
;
1522 for (size_t i
= 1; i
< children
.size(); i
++)
1524 log_assert(children
.at(i
)->type
== AST_COND
|| children
.at(i
)->type
== AST_CONDX
|| children
.at(i
)->type
== AST_CONDZ
);
1526 AstNode
*this_genblock
= NULL
;
1527 for (auto child
: children
.at(i
)->children
) {
1528 log_assert(this_genblock
== NULL
);
1529 if (child
->type
== AST_GENBLOCK
)
1530 this_genblock
= child
;
1533 for (auto child
: children
.at(i
)->children
)
1535 if (child
->type
== AST_DEFAULT
) {
1536 if (selected_case
== NULL
)
1537 selected_case
= this_genblock
;
1540 if (child
->type
== AST_GENBLOCK
)
1543 buf
= child
->clone();
1544 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1545 if (buf
->type
!= AST_CONSTANT
) {
1546 // for (auto f : log_files)
1547 // dumpAst(f, "verilog-ast> ");
1548 log_file_error(filename
, linenum
, "Expression in generate case is not constant!\n");
1551 bool is_selected
= RTLIL::const_eq(ref_value
, buf
->bitsAsConst(), ref_signed
&& buf
->is_signed
, ref_signed
&& buf
->is_signed
, 1).as_bool();
1555 selected_case
= this_genblock
;
1556 i
= children
.size();
1562 if (selected_case
!= NULL
)
1564 log_assert(selected_case
->type
== AST_GENBLOCK
);
1565 buf
= selected_case
->clone();
1567 if (!buf
->str
.empty()) {
1568 std::map
<std::string
, std::string
> name_map
;
1569 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1572 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1573 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1574 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1577 buf
->children
.clear();
1582 did_something
= true;
1585 // unroll cell arrays
1586 if (type
== AST_CELLARRAY
)
1588 if (!children
.at(0)->range_valid
)
1589 log_file_error(filename
, linenum
, "Non-constant array range on cell array.\n");
1591 newNode
= new AstNode(AST_GENBLOCK
);
1592 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;
1594 for (int i
= 0; i
< num
; i
++) {
1595 int idx
= children
.at(0)->range_left
> children
.at(0)->range_right
? children
.at(0)->range_right
+ i
: children
.at(0)->range_right
- i
;
1596 AstNode
*new_cell
= children
.at(1)->clone();
1597 newNode
->children
.push_back(new_cell
);
1598 new_cell
->str
+= stringf("[%d]", idx
);
1599 if (new_cell
->type
== AST_PRIMITIVE
) {
1600 log_file_error(filename
, linenum
, "Cell arrays of primitives are currently not supported.\n");
1602 log_assert(new_cell
->children
.at(0)->type
== AST_CELLTYPE
);
1603 new_cell
->children
.at(0)->str
= stringf("$array:%d:%d:%s", i
, num
, new_cell
->children
.at(0)->str
.c_str());
1610 // replace primitives with assignments
1611 if (type
== AST_PRIMITIVE
)
1613 if (children
.size() < 2)
1614 log_file_error(filename
, linenum
, "Insufficient number of arguments for primitive `%s'!\n", str
.c_str());
1616 std::vector
<AstNode
*> children_list
;
1617 for (auto child
: children
) {
1618 log_assert(child
->type
== AST_ARGUMENT
);
1619 log_assert(child
->children
.size() == 1);
1620 children_list
.push_back(child
->children
[0]);
1621 child
->children
.clear();
1626 if (str
== "bufif0" || str
== "bufif1" || str
== "notif0" || str
== "notif1")
1628 if (children_list
.size() != 3)
1629 log_file_error(filename
, linenum
, "Invalid number of arguments for primitive `%s'!\n", str
.c_str());
1631 std::vector
<RTLIL::State
> z_const(1, RTLIL::State::Sz
);
1633 AstNode
*mux_input
= children_list
.at(1);
1634 if (str
== "notif0" || str
== "notif1") {
1635 mux_input
= new AstNode(AST_BIT_NOT
, mux_input
);
1637 AstNode
*node
= new AstNode(AST_TERNARY
, children_list
.at(2));
1638 if (str
== "bufif0") {
1639 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1640 node
->children
.push_back(mux_input
);
1642 node
->children
.push_back(mux_input
);
1643 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1648 children
.push_back(children_list
.at(0));
1649 children
.back()->was_checked
= true;
1650 children
.push_back(node
);
1651 did_something
= true;
1655 AstNodeType op_type
= AST_NONE
;
1656 bool invert_results
= false;
1659 op_type
= AST_BIT_AND
;
1661 op_type
= AST_BIT_AND
, invert_results
= true;
1663 op_type
= AST_BIT_OR
;
1665 op_type
= AST_BIT_OR
, invert_results
= true;
1667 op_type
= AST_BIT_XOR
;
1669 op_type
= AST_BIT_XOR
, invert_results
= true;
1673 op_type
= AST_POS
, invert_results
= true;
1674 log_assert(op_type
!= AST_NONE
);
1676 AstNode
*node
= children_list
[1];
1677 if (op_type
!= AST_POS
)
1678 for (size_t i
= 2; i
< children_list
.size(); i
++)
1679 node
= new AstNode(op_type
, node
, children_list
[i
]);
1681 node
= new AstNode(AST_BIT_NOT
, node
);
1685 children
.push_back(children_list
[0]);
1686 children
.back()->was_checked
= true;
1687 children
.push_back(node
);
1688 did_something
= true;
1692 // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
1693 // a big case block that selects the correct single-bit assignment.
1694 if (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) {
1695 if (children
[0]->type
!= AST_IDENTIFIER
|| children
[0]->children
.size() == 0)
1696 goto skip_dynamic_range_lvalue_expansion
;
1697 if (children
[0]->children
[0]->range_valid
|| did_something
)
1698 goto skip_dynamic_range_lvalue_expansion
;
1699 if (children
[0]->id2ast
== NULL
|| children
[0]->id2ast
->type
!= AST_WIRE
)
1700 goto skip_dynamic_range_lvalue_expansion
;
1701 if (!children
[0]->id2ast
->range_valid
)
1702 goto skip_dynamic_range_lvalue_expansion
;
1703 int source_width
= children
[0]->id2ast
->range_left
- children
[0]->id2ast
->range_right
+ 1;
1704 int result_width
= 1;
1705 AstNode
*shift_expr
= NULL
;
1706 AstNode
*range
= children
[0]->children
[0];
1707 if (range
->children
.size() == 1) {
1708 shift_expr
= range
->children
[0]->clone();
1710 shift_expr
= range
->children
[1]->clone();
1711 AstNode
*left_at_zero_ast
= range
->children
[0]->clone();
1712 AstNode
*right_at_zero_ast
= range
->children
[1]->clone();
1713 while (left_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1714 while (right_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1715 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
1716 log_file_error(filename
, linenum
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
1717 result_width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
1719 did_something
= true;
1720 newNode
= new AstNode(AST_CASE
, shift_expr
);
1721 for (int i
= 0; i
<= source_width
-result_width
; i
++) {
1722 int start_bit
= children
[0]->id2ast
->range_right
+ i
;
1723 AstNode
*cond
= new AstNode(AST_COND
, mkconst_int(start_bit
, true));
1724 AstNode
*lvalue
= children
[0]->clone();
1725 lvalue
->delete_children();
1726 lvalue
->children
.push_back(new AstNode(AST_RANGE
,
1727 mkconst_int(start_bit
+result_width
-1, true), mkconst_int(start_bit
, true)));
1728 cond
->children
.push_back(new AstNode(AST_BLOCK
, new AstNode(type
, lvalue
, children
[1]->clone())));
1729 newNode
->children
.push_back(cond
);
1733 skip_dynamic_range_lvalue_expansion
:;
1735 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && current_block
!= NULL
)
1737 std::stringstream sstr
;
1738 sstr
<< "$formal$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1739 std::string id_check
= sstr
.str() + "_CHECK", id_en
= sstr
.str() + "_EN";
1741 AstNode
*wire_check
= new AstNode(AST_WIRE
);
1742 wire_check
->str
= id_check
;
1743 wire_check
->was_checked
= true;
1744 current_ast_mod
->children
.push_back(wire_check
);
1745 current_scope
[wire_check
->str
] = wire_check
;
1746 while (wire_check
->simplify(true, false, false, 1, -1, false, false)) { }
1748 AstNode
*wire_en
= new AstNode(AST_WIRE
);
1749 wire_en
->str
= id_en
;
1750 wire_en
->was_checked
= true;
1751 current_ast_mod
->children
.push_back(wire_en
);
1752 if (current_always_clocked
) {
1753 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)))));
1754 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->str
= id_en
;
1755 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->was_checked
= true;
1757 current_scope
[wire_en
->str
] = wire_en
;
1758 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
1760 AstNode
*check_defval
;
1761 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
1762 check_defval
= new AstNode(AST_REDUCE_BOOL
, children
[0]->clone());
1764 std::vector
<RTLIL::State
> x_bit
;
1765 x_bit
.push_back(RTLIL::State::Sx
);
1766 check_defval
= mkconst_bits(x_bit
, false);
1769 AstNode
*assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), check_defval
);
1770 assign_check
->children
[0]->str
= id_check
;
1771 assign_check
->children
[0]->was_checked
= true;
1773 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, 1));
1774 assign_en
->children
[0]->str
= id_en
;
1775 assign_en
->children
[0]->was_checked
= true;
1777 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
1778 default_signals
->children
.push_back(assign_check
);
1779 default_signals
->children
.push_back(assign_en
);
1780 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
1782 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
1783 assign_check
= nullptr;
1785 assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_REDUCE_BOOL
, children
[0]->clone()));
1786 assign_check
->children
[0]->str
= id_check
;
1787 assign_check
->children
[0]->was_checked
= true;
1790 if (current_always
== nullptr || current_always
->type
!= AST_INITIAL
) {
1791 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(1, false, 1));
1793 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_FCALL
));
1794 assign_en
->children
[1]->str
= "\\$initstate";
1796 assign_en
->children
[0]->str
= id_en
;
1797 assign_en
->children
[0]->was_checked
= true;
1799 newNode
= new AstNode(AST_BLOCK
);
1800 if (assign_check
!= nullptr)
1801 newNode
->children
.push_back(assign_check
);
1802 newNode
->children
.push_back(assign_en
);
1804 AstNode
*assertnode
= new AstNode(type
);
1805 assertnode
->str
= str
;
1806 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1807 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1808 assertnode
->children
[0]->str
= id_check
;
1809 assertnode
->children
[1]->str
= id_en
;
1810 assertnode
->attributes
.swap(attributes
);
1811 current_ast_mod
->children
.push_back(assertnode
);
1816 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && children
.size() == 1)
1818 children
.push_back(mkconst_int(1, false, 1));
1819 did_something
= true;
1822 // found right-hand side identifier for memory -> replace with memory read port
1823 if (stage
> 1 && type
== AST_IDENTIFIER
&& id2ast
!= NULL
&& id2ast
->type
== AST_MEMORY
&& !in_lvalue
&&
1824 children
.size() == 1 && children
[0]->type
== AST_RANGE
&& children
[0]->children
.size() == 1) {
1825 newNode
= new AstNode(AST_MEMRD
, children
[0]->children
[0]->clone());
1827 newNode
->id2ast
= id2ast
;
1831 // assignment with nontrivial member in left-hand concat expression -> split assignment
1832 if ((type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_CONCAT
&& width_hint
> 0)
1834 bool found_nontrivial_member
= false;
1836 for (auto child
: children
[0]->children
) {
1837 if (child
->type
== AST_IDENTIFIER
&& child
->id2ast
!= NULL
&& child
->id2ast
->type
== AST_MEMORY
)
1838 found_nontrivial_member
= true;
1841 if (found_nontrivial_member
)
1843 newNode
= new AstNode(AST_BLOCK
);
1845 AstNode
*wire_tmp
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
1846 wire_tmp
->str
= stringf("$splitcmplxassign$%s:%d$%d", filename
.c_str(), linenum
, autoidx
++);
1847 current_ast_mod
->children
.push_back(wire_tmp
);
1848 current_scope
[wire_tmp
->str
] = wire_tmp
;
1849 wire_tmp
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
1850 while (wire_tmp
->simplify(true, false, false, 1, -1, false, false)) { }
1851 wire_tmp
->is_logic
= true;
1853 AstNode
*wire_tmp_id
= new AstNode(AST_IDENTIFIER
);
1854 wire_tmp_id
->str
= wire_tmp
->str
;
1856 newNode
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, wire_tmp_id
, children
[1]->clone()));
1857 newNode
->children
.back()->was_checked
= true;
1860 for (auto child
: children
[0]->children
)
1862 int child_width_hint
= -1;
1863 bool child_sign_hint
= true;
1864 child
->detectSignWidth(child_width_hint
, child_sign_hint
);
1866 AstNode
*rhs
= wire_tmp_id
->clone();
1867 rhs
->children
.push_back(new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+child_width_hint
-1, true), AstNode::mkconst_int(cursor
, true)));
1868 newNode
->children
.push_back(new AstNode(type
, child
->clone(), rhs
));
1870 cursor
+= child_width_hint
;
1877 // assignment with memory in left-hand side expression -> replace with memory write port
1878 if (stage
> 1 && (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_IDENTIFIER
&&
1879 children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
&& children
[0]->id2ast
->children
.size() >= 2 &&
1880 children
[0]->id2ast
->children
[0]->range_valid
&& children
[0]->id2ast
->children
[1]->range_valid
&&
1881 (children
[0]->children
.size() == 1 || children
[0]->children
.size() == 2) && children
[0]->children
[0]->type
== AST_RANGE
)
1883 std::stringstream sstr
;
1884 sstr
<< "$memwr$" << children
[0]->str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1885 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA", id_en
= sstr
.str() + "_EN";
1887 int mem_width
, mem_size
, addr_bits
;
1888 bool mem_signed
= children
[0]->id2ast
->is_signed
;
1889 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
1891 int data_range_left
= children
[0]->id2ast
->children
[0]->range_left
;
1892 int data_range_right
= children
[0]->id2ast
->children
[0]->range_right
;
1893 int mem_data_range_offset
= std::min(data_range_left
, data_range_right
);
1895 int addr_width_hint
= -1;
1896 bool addr_sign_hint
= true;
1897 children
[0]->children
[0]->children
[0]->detectSignWidthWorker(addr_width_hint
, addr_sign_hint
);
1898 addr_bits
= std::max(addr_bits
, addr_width_hint
);
1900 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
1901 wire_addr
->str
= id_addr
;
1902 wire_addr
->was_checked
= true;
1903 current_ast_mod
->children
.push_back(wire_addr
);
1904 current_scope
[wire_addr
->str
] = wire_addr
;
1905 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
1907 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
1908 wire_data
->str
= id_data
;
1909 wire_data
->was_checked
= true;
1910 wire_data
->is_signed
= mem_signed
;
1911 current_ast_mod
->children
.push_back(wire_data
);
1912 current_scope
[wire_data
->str
] = wire_data
;
1913 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
1915 AstNode
*wire_en
= nullptr;
1916 if (current_always
->type
!= AST_INITIAL
) {
1917 wire_en
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
1918 wire_en
->str
= id_en
;
1919 wire_en
->was_checked
= true;
1920 current_ast_mod
->children
.push_back(wire_en
);
1921 current_scope
[wire_en
->str
] = wire_en
;
1922 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
1925 std::vector
<RTLIL::State
> x_bits_addr
, x_bits_data
, set_bits_en
;
1926 for (int i
= 0; i
< addr_bits
; i
++)
1927 x_bits_addr
.push_back(RTLIL::State::Sx
);
1928 for (int i
= 0; i
< mem_width
; i
++)
1929 x_bits_data
.push_back(RTLIL::State::Sx
);
1930 for (int i
= 0; i
< mem_width
; i
++)
1931 set_bits_en
.push_back(RTLIL::State::S1
);
1933 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_addr
, false));
1934 assign_addr
->children
[0]->str
= id_addr
;
1935 assign_addr
->children
[0]->was_checked
= true;
1937 AstNode
*assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_data
, false));
1938 assign_data
->children
[0]->str
= id_data
;
1939 assign_data
->children
[0]->was_checked
= true;
1941 AstNode
*assign_en
= nullptr;
1942 if (current_always
->type
!= AST_INITIAL
) {
1943 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, mem_width
));
1944 assign_en
->children
[0]->str
= id_en
;
1945 assign_en
->children
[0]->was_checked
= true;
1948 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
1949 default_signals
->children
.push_back(assign_addr
);
1950 default_signals
->children
.push_back(assign_data
);
1951 if (current_always
->type
!= AST_INITIAL
)
1952 default_signals
->children
.push_back(assign_en
);
1953 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
1955 assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
1956 assign_addr
->children
[0]->str
= id_addr
;
1957 assign_addr
->children
[0]->was_checked
= true;
1959 if (children
[0]->children
.size() == 2)
1961 if (children
[0]->children
[1]->range_valid
)
1963 int offset
= children
[0]->children
[1]->range_right
;
1964 int width
= children
[0]->children
[1]->range_left
- offset
+ 1;
1965 offset
-= mem_data_range_offset
;
1967 std::vector
<RTLIL::State
> padding_x(offset
, RTLIL::State::Sx
);
1969 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1970 new AstNode(AST_CONCAT
, mkconst_bits(padding_x
, false), children
[1]->clone()));
1971 assign_data
->children
[0]->str
= id_data
;
1972 assign_data
->children
[0]->was_checked
= true;
1974 if (current_always
->type
!= AST_INITIAL
) {
1975 for (int i
= 0; i
< mem_width
; i
++)
1976 set_bits_en
[i
] = offset
<= i
&& i
< offset
+width
? RTLIL::State::S1
: RTLIL::State::S0
;
1977 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
1978 assign_en
->children
[0]->str
= id_en
;
1979 assign_en
->children
[0]->was_checked
= true;
1984 AstNode
*the_range
= children
[0]->children
[1];
1985 AstNode
*left_at_zero_ast
= the_range
->children
[0]->clone();
1986 AstNode
*right_at_zero_ast
= the_range
->children
.size() >= 2 ? the_range
->children
[1]->clone() : left_at_zero_ast
->clone();
1987 AstNode
*offset_ast
= right_at_zero_ast
->clone();
1989 if (mem_data_range_offset
)
1990 offset_ast
= new AstNode(AST_SUB
, offset_ast
, mkconst_int(mem_data_range_offset
, true));
1992 while (left_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
1993 while (right_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
1994 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
1995 log_file_error(filename
, linenum
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
1996 int width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
1998 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1999 new AstNode(AST_SHIFT_LEFT
, children
[1]->clone(), offset_ast
->clone()));
2000 assign_data
->children
[0]->str
= id_data
;
2001 assign_data
->children
[0]->was_checked
= true;
2003 if (current_always
->type
!= AST_INITIAL
) {
2004 for (int i
= 0; i
< mem_width
; i
++)
2005 set_bits_en
[i
] = i
< width
? RTLIL::State::S1
: RTLIL::State::S0
;
2006 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
2007 new AstNode(AST_SHIFT_LEFT
, mkconst_bits(set_bits_en
, false), offset_ast
->clone()));
2008 assign_en
->children
[0]->str
= id_en
;
2009 assign_en
->children
[0]->was_checked
= true;
2012 delete left_at_zero_ast
;
2013 delete right_at_zero_ast
;
2019 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[1]->clone());
2020 assign_data
->children
[0]->str
= id_data
;
2021 assign_data
->children
[0]->was_checked
= true;
2023 if (current_always
->type
!= AST_INITIAL
) {
2024 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
2025 assign_en
->children
[0]->str
= id_en
;
2026 assign_en
->children
[0]->was_checked
= true;
2030 newNode
= new AstNode(AST_BLOCK
);
2031 newNode
->children
.push_back(assign_addr
);
2032 newNode
->children
.push_back(assign_data
);
2033 if (current_always
->type
!= AST_INITIAL
)
2034 newNode
->children
.push_back(assign_en
);
2036 AstNode
*wrnode
= new AstNode(current_always
->type
== AST_INITIAL
? AST_MEMINIT
: AST_MEMWR
);
2037 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
2038 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
2039 if (current_always
->type
!= AST_INITIAL
)
2040 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
2042 wrnode
->children
.push_back(AstNode::mkconst_int(1, false));
2043 wrnode
->str
= children
[0]->str
;
2044 wrnode
->id2ast
= children
[0]->id2ast
;
2045 wrnode
->children
[0]->str
= id_addr
;
2046 wrnode
->children
[1]->str
= id_data
;
2047 if (current_always
->type
!= AST_INITIAL
)
2048 wrnode
->children
[2]->str
= id_en
;
2049 current_ast_mod
->children
.push_back(wrnode
);
2054 // replace function and task calls with the code from the function or task
2055 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && !str
.empty())
2057 if (type
== AST_FCALL
)
2059 if (str
== "\\$initstate")
2061 int myidx
= autoidx
++;
2063 AstNode
*wire
= new AstNode(AST_WIRE
);
2064 wire
->str
= stringf("$initstate$%d_wire", myidx
);
2065 current_ast_mod
->children
.push_back(wire
);
2066 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2068 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
), new AstNode(AST_ARGUMENT
, new AstNode(AST_IDENTIFIER
)));
2069 cell
->str
= stringf("$initstate$%d", myidx
);
2070 cell
->children
[0]->str
= "$initstate";
2071 cell
->children
[1]->str
= "\\Y";
2072 cell
->children
[1]->children
[0]->str
= wire
->str
;
2073 cell
->children
[1]->children
[0]->id2ast
= wire
;
2074 current_ast_mod
->children
.push_back(cell
);
2075 while (cell
->simplify(true, false, false, 1, -1, false, false)) { }
2077 newNode
= new AstNode(AST_IDENTIFIER
);
2078 newNode
->str
= wire
->str
;
2079 newNode
->id2ast
= wire
;
2083 if (str
== "\\$past")
2086 goto replace_fcall_later
;
2090 if (GetSize(children
) != 1 && GetSize(children
) != 2)
2091 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1 or 2.\n",
2092 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2094 if (!current_always_clocked
)
2095 log_file_error(filename
, linenum
, "System function %s is only allowed in clocked blocks.\n",
2096 RTLIL::unescape_id(str
).c_str());
2098 if (GetSize(children
) == 2)
2100 AstNode
*buf
= children
[1]->clone();
2101 while (buf
->simplify(true, false, false, stage
, -1, false, false)) { }
2102 if (buf
->type
!= AST_CONSTANT
)
2103 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
2105 num_steps
= buf
->asInt(true);
2109 AstNode
*block
= nullptr;
2111 for (auto child
: current_always
->children
)
2112 if (child
->type
== AST_BLOCK
)
2115 log_assert(block
!= nullptr);
2117 if (num_steps
== 0) {
2118 newNode
= children
[0]->clone();
2122 int myidx
= autoidx
++;
2123 AstNode
*outreg
= nullptr;
2125 for (int i
= 0; i
< num_steps
; i
++)
2127 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
2128 mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
2130 reg
->str
= stringf("$past$%s:%d$%d$%d", filename
.c_str(), linenum
, myidx
, i
);
2133 current_ast_mod
->children
.push_back(reg
);
2135 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
2137 AstNode
*regid
= new AstNode(AST_IDENTIFIER
);
2138 regid
->str
= reg
->str
;
2139 regid
->id2ast
= reg
;
2140 regid
->was_checked
= true;
2142 AstNode
*rhs
= nullptr;
2144 if (outreg
== nullptr) {
2145 rhs
= children
.at(0)->clone();
2147 rhs
= new AstNode(AST_IDENTIFIER
);
2148 rhs
->str
= outreg
->str
;
2149 rhs
->id2ast
= outreg
;
2152 block
->children
.push_back(new AstNode(AST_ASSIGN_LE
, regid
, rhs
));
2156 newNode
= new AstNode(AST_IDENTIFIER
);
2157 newNode
->str
= outreg
->str
;
2158 newNode
->id2ast
= outreg
;
2162 if (str
== "\\$stable" || str
== "\\$rose" || str
== "\\$fell" || str
== "\\$changed")
2164 if (GetSize(children
) != 1)
2165 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1.\n",
2166 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2168 if (!current_always_clocked
)
2169 log_file_error(filename
, linenum
, "System function %s is only allowed in clocked blocks.\n",
2170 RTLIL::unescape_id(str
).c_str());
2172 AstNode
*present
= children
.at(0)->clone();
2173 AstNode
*past
= clone();
2174 past
->str
= "\\$past";
2176 if (str
== "\\$stable")
2177 newNode
= new AstNode(AST_EQ
, past
, present
);
2179 else if (str
== "\\$changed")
2180 newNode
= new AstNode(AST_NE
, past
, present
);
2182 else if (str
== "\\$rose")
2183 newNode
= new AstNode(AST_LOGIC_AND
,
2184 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false))),
2185 new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false)));
2187 else if (str
== "\\$fell")
2188 newNode
= new AstNode(AST_LOGIC_AND
,
2189 new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false)),
2190 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false))));
2198 // $anyconst and $anyseq are mapped in AstNode::genRTLIL()
2199 if (str
== "\\$anyconst" || str
== "\\$anyseq" || str
== "\\$allconst" || str
== "\\$allseq") {
2200 recursion_counter
--;
2204 if (str
== "\\$clog2")
2206 if (children
.size() != 1)
2207 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1.\n",
2208 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2210 AstNode
*buf
= children
[0]->clone();
2211 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2212 if (buf
->type
!= AST_CONSTANT
)
2213 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
2215 RTLIL::Const arg_value
= buf
->bitsAsConst();
2216 if (arg_value
.as_bool())
2217 arg_value
= const_sub(arg_value
, 1, false, false, GetSize(arg_value
));
2220 uint32_t result
= 0;
2221 for (size_t i
= 0; i
< arg_value
.bits
.size(); i
++)
2222 if (arg_value
.bits
.at(i
) == RTLIL::State::S1
)
2225 newNode
= mkconst_int(result
, true);
2229 if (str
== "\\$size" || str
== "\\$bits")
2231 if (str
== "\\$bits" && children
.size() != 1)
2232 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1.\n",
2233 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2235 if (str
== "\\$size" && children
.size() != 1 && children
.size() != 2)
2236 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1 or 2.\n",
2237 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2240 if (str
== "\\$size" && children
.size() == 2) {
2241 AstNode
*buf
= children
[1]->clone();
2242 // Evaluate constant expression
2243 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2244 dim
= buf
->asInt(false);
2247 AstNode
*buf
= children
[0]->clone();
2249 AstNode
*id_ast
= NULL
;
2252 //while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2253 buf
->detectSignWidth(width_hint
, sign_hint
);
2255 if (buf
->type
== AST_IDENTIFIER
) {
2256 id_ast
= buf
->id2ast
;
2257 if (id_ast
== NULL
&& current_scope
.count(buf
->str
))
2258 id_ast
= current_scope
.at(buf
->str
);
2260 log_file_error(filename
, linenum
, "Failed to resolve identifier %s for width detection!\n", buf
->str
.c_str());
2261 if (id_ast
->type
== AST_MEMORY
) {
2262 // We got here only if the argument is a memory
2263 // Otherwise $size() and $bits() return the expression width
2264 AstNode
*mem_range
= id_ast
->children
[1];
2265 if (str
== "\\$bits") {
2266 if (mem_range
->type
== AST_RANGE
) {
2267 if (!mem_range
->range_valid
)
2268 log_file_error(filename
, linenum
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2269 mem_depth
= mem_range
->range_left
- mem_range
->range_right
+ 1;
2271 log_file_error(filename
, linenum
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2274 if (mem_range
->type
== AST_RANGE
) {
2275 if (!mem_range
->range_valid
)
2276 log_file_error(filename
, linenum
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2278 if (id_ast
->multirange_dimensions
.empty())
2281 dims
= GetSize(id_ast
->multirange_dimensions
)/2;
2283 width_hint
= (dims
> 1) ? id_ast
->multirange_dimensions
[1] : (mem_range
->range_left
- mem_range
->range_right
+ 1);
2284 else if (dim
<= dims
) {
2285 width_hint
= id_ast
->multirange_dimensions
[2*dim
-1];
2286 } else if ((dim
> dims
+1) || (dim
< 0))
2287 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);
2289 log_file_error(filename
, linenum
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2295 newNode
= mkconst_int(width_hint
* mem_depth
, false);
2299 if (str
== "\\$ln" || str
== "\\$log10" || str
== "\\$exp" || str
== "\\$sqrt" || str
== "\\$pow" ||
2300 str
== "\\$floor" || str
== "\\$ceil" || str
== "\\$sin" || str
== "\\$cos" || str
== "\\$tan" ||
2301 str
== "\\$asin" || str
== "\\$acos" || str
== "\\$atan" || str
== "\\$atan2" || str
== "\\$hypot" ||
2302 str
== "\\$sinh" || str
== "\\$cosh" || str
== "\\$tanh" || str
== "\\$asinh" || str
== "\\$acosh" || str
== "\\$atanh" ||
2303 str
== "\\$rtoi" || str
== "\\$itor")
2305 bool func_with_two_arguments
= str
== "\\$pow" || str
== "\\$atan2" || str
== "\\$hypot";
2306 double x
= 0, y
= 0;
2308 if (func_with_two_arguments
) {
2309 if (children
.size() != 2)
2310 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 2.\n",
2311 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2313 if (children
.size() != 1)
2314 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1.\n",
2315 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2318 if (children
.size() >= 1) {
2319 while (children
[0]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2320 if (!children
[0]->isConst())
2321 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant argument.\n",
2322 RTLIL::unescape_id(str
).c_str());
2323 int child_width_hint
= width_hint
;
2324 bool child_sign_hint
= sign_hint
;
2325 children
[0]->detectSignWidth(child_width_hint
, child_sign_hint
);
2326 x
= children
[0]->asReal(child_sign_hint
);
2329 if (children
.size() >= 2) {
2330 while (children
[1]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2331 if (!children
[1]->isConst())
2332 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant argument.\n",
2333 RTLIL::unescape_id(str
).c_str());
2334 int child_width_hint
= width_hint
;
2335 bool child_sign_hint
= sign_hint
;
2336 children
[1]->detectSignWidth(child_width_hint
, child_sign_hint
);
2337 y
= children
[1]->asReal(child_sign_hint
);
2340 if (str
== "\\$rtoi") {
2341 newNode
= AstNode::mkconst_int(x
, true);
2343 newNode
= new AstNode(AST_REALVALUE
);
2344 if (str
== "\\$ln") newNode
->realvalue
= ::log(x
);
2345 else if (str
== "\\$log10") newNode
->realvalue
= ::log10(x
);
2346 else if (str
== "\\$exp") newNode
->realvalue
= ::exp(x
);
2347 else if (str
== "\\$sqrt") newNode
->realvalue
= ::sqrt(x
);
2348 else if (str
== "\\$pow") newNode
->realvalue
= ::pow(x
, y
);
2349 else if (str
== "\\$floor") newNode
->realvalue
= ::floor(x
);
2350 else if (str
== "\\$ceil") newNode
->realvalue
= ::ceil(x
);
2351 else if (str
== "\\$sin") newNode
->realvalue
= ::sin(x
);
2352 else if (str
== "\\$cos") newNode
->realvalue
= ::cos(x
);
2353 else if (str
== "\\$tan") newNode
->realvalue
= ::tan(x
);
2354 else if (str
== "\\$asin") newNode
->realvalue
= ::asin(x
);
2355 else if (str
== "\\$acos") newNode
->realvalue
= ::acos(x
);
2356 else if (str
== "\\$atan") newNode
->realvalue
= ::atan(x
);
2357 else if (str
== "\\$atan2") newNode
->realvalue
= ::atan2(x
, y
);
2358 else if (str
== "\\$hypot") newNode
->realvalue
= ::hypot(x
, y
);
2359 else if (str
== "\\$sinh") newNode
->realvalue
= ::sinh(x
);
2360 else if (str
== "\\$cosh") newNode
->realvalue
= ::cosh(x
);
2361 else if (str
== "\\$tanh") newNode
->realvalue
= ::tanh(x
);
2362 else if (str
== "\\$asinh") newNode
->realvalue
= ::asinh(x
);
2363 else if (str
== "\\$acosh") newNode
->realvalue
= ::acosh(x
);
2364 else if (str
== "\\$atanh") newNode
->realvalue
= ::atanh(x
);
2365 else if (str
== "\\$itor") newNode
->realvalue
= x
;
2371 if (current_scope
.count(str
) != 0 && current_scope
[str
]->type
== AST_DPI_FUNCTION
)
2373 AstNode
*dpi_decl
= current_scope
[str
];
2375 std::string rtype
, fname
;
2376 std::vector
<std::string
> argtypes
;
2377 std::vector
<AstNode
*> args
;
2379 rtype
= RTLIL::unescape_id(dpi_decl
->children
.at(0)->str
);
2380 fname
= RTLIL::unescape_id(dpi_decl
->children
.at(1)->str
);
2382 for (int i
= 2; i
< GetSize(dpi_decl
->children
); i
++)
2384 if (i
-2 >= GetSize(children
))
2385 log_file_error(filename
, linenum
, "Insufficient number of arguments in DPI function call.\n");
2387 argtypes
.push_back(RTLIL::unescape_id(dpi_decl
->children
.at(i
)->str
));
2388 args
.push_back(children
.at(i
-2)->clone());
2389 while (args
.back()->simplify(true, false, false, stage
, -1, false, true)) { }
2391 if (args
.back()->type
!= AST_CONSTANT
&& args
.back()->type
!= AST_REALVALUE
)
2392 log_file_error(filename
, linenum
, "Failed to evaluate DPI function with non-constant argument.\n");
2395 newNode
= dpi_call(rtype
, fname
, argtypes
, args
);
2397 for (auto arg
: args
)
2403 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_FUNCTION
)
2404 log_file_error(filename
, linenum
, "Can't resolve function name `%s'.\n", str
.c_str());
2407 if (type
== AST_TCALL
)
2409 if (str
== "$finish" || str
== "$stop")
2411 if (!current_always
|| current_always
->type
!= AST_INITIAL
)
2412 log_file_error(filename
, linenum
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
2414 log_file_error(filename
, linenum
, "System task `%s' executed.\n", str
.c_str());
2417 if (str
== "\\$readmemh" || str
== "\\$readmemb")
2419 if (GetSize(children
) < 2 || GetSize(children
) > 4)
2420 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 2-4.\n",
2421 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2423 AstNode
*node_filename
= children
[0]->clone();
2424 while (node_filename
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2425 if (node_filename
->type
!= AST_CONSTANT
)
2426 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
2428 AstNode
*node_memory
= children
[1]->clone();
2429 while (node_memory
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2430 if (node_memory
->type
!= AST_IDENTIFIER
|| node_memory
->id2ast
== nullptr || node_memory
->id2ast
->type
!= AST_MEMORY
)
2431 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str
.c_str());
2433 int start_addr
= -1, finish_addr
= -1;
2435 if (GetSize(children
) > 2) {
2436 AstNode
*node_addr
= children
[2]->clone();
2437 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2438 if (node_addr
->type
!= AST_CONSTANT
)
2439 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str
.c_str());
2440 start_addr
= int(node_addr
->asInt(false));
2443 if (GetSize(children
) > 3) {
2444 AstNode
*node_addr
= children
[3]->clone();
2445 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2446 if (node_addr
->type
!= AST_CONSTANT
)
2447 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str
.c_str());
2448 finish_addr
= int(node_addr
->asInt(false));
2451 bool unconditional_init
= false;
2452 if (current_always
->type
== AST_INITIAL
) {
2453 pool
<AstNode
*> queue
;
2454 log_assert(current_always
->children
[0]->type
== AST_BLOCK
);
2455 queue
.insert(current_always
->children
[0]);
2456 while (!unconditional_init
&& !queue
.empty()) {
2457 pool
<AstNode
*> next_queue
;
2458 for (auto n
: queue
)
2459 for (auto c
: n
->children
) {
2461 unconditional_init
= true;
2462 next_queue
.insert(c
);
2464 next_queue
.swap(queue
);
2468 newNode
= readmem(str
== "\\$readmemh", node_filename
->bitsAsConst().decode_string(), node_memory
->id2ast
, start_addr
, finish_addr
, unconditional_init
);
2469 delete node_filename
;
2474 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_TASK
)
2475 log_file_error(filename
, linenum
, "Can't resolve task name `%s'.\n", str
.c_str());
2478 AstNode
*decl
= current_scope
[str
];
2480 std::stringstream sstr
;
2481 sstr
<< "$func$" << str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++) << "$";
2482 std::string prefix
= sstr
.str();
2484 bool recommend_const_eval
= false;
2485 bool require_const_eval
= in_param
? false : has_const_only_constructs(recommend_const_eval
);
2486 if ((in_param
|| recommend_const_eval
|| require_const_eval
) && !decl
->attributes
.count("\\via_celltype"))
2488 bool all_args_const
= true;
2489 for (auto child
: children
) {
2490 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
2491 if (child
->type
!= AST_CONSTANT
)
2492 all_args_const
= false;
2495 if (all_args_const
) {
2496 AstNode
*func_workspace
= current_scope
[str
]->clone();
2497 newNode
= func_workspace
->eval_const_function(this);
2498 delete func_workspace
;
2503 log_file_error(filename
, linenum
, "Non-constant function call in constant expression.\n");
2504 if (require_const_eval
)
2505 log_file_error(filename
, linenum
, "Function %s can only be called with constant arguments.\n", str
.c_str());
2508 size_t arg_count
= 0;
2509 std::map
<std::string
, std::string
> replace_rules
;
2510 vector
<AstNode
*> added_mod_children
;
2511 dict
<std::string
, AstNode
*> wire_cache
;
2512 vector
<AstNode
*> new_stmts
;
2513 vector
<AstNode
*> output_assignments
;
2515 if (current_block
== NULL
)
2517 log_assert(type
== AST_FCALL
);
2519 AstNode
*wire
= NULL
;
2520 for (auto child
: decl
->children
)
2521 if (child
->type
== AST_WIRE
&& child
->str
== str
)
2522 wire
= child
->clone();
2523 log_assert(wire
!= NULL
);
2525 wire
->str
= prefix
+ str
;
2527 wire
->is_input
= false;
2528 wire
->is_output
= false;
2530 current_ast_mod
->children
.push_back(wire
);
2531 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2533 AstNode
*lvalue
= new AstNode(AST_IDENTIFIER
);
2534 lvalue
->str
= wire
->str
;
2536 AstNode
*always
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
,
2537 new AstNode(AST_ASSIGN_EQ
, lvalue
, clone())));
2538 always
->children
[0]->children
[0]->was_checked
= true;
2540 current_ast_mod
->children
.push_back(always
);
2542 goto replace_fcall_with_id
;
2545 if (decl
->attributes
.count("\\via_celltype"))
2547 std::string celltype
= decl
->attributes
.at("\\via_celltype")->asAttrConst().decode_string();
2548 std::string outport
= str
;
2550 if (celltype
.find(' ') != std::string::npos
) {
2551 int pos
= celltype
.find(' ');
2552 outport
= RTLIL::escape_id(celltype
.substr(pos
+1));
2553 celltype
= RTLIL::escape_id(celltype
.substr(0, pos
));
2555 celltype
= RTLIL::escape_id(celltype
);
2557 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
));
2558 cell
->str
= prefix
.substr(0, GetSize(prefix
)-1);
2559 cell
->children
[0]->str
= celltype
;
2561 for (auto attr
: decl
->attributes
)
2562 if (attr
.first
.str().rfind("\\via_celltype_defparam_", 0) == 0)
2564 AstNode
*cell_arg
= new AstNode(AST_PARASET
, attr
.second
->clone());
2565 cell_arg
->str
= RTLIL::escape_id(attr
.first
.substr(strlen("\\via_celltype_defparam_")));
2566 cell
->children
.push_back(cell_arg
);
2569 for (auto child
: decl
->children
)
2570 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
|| (type
== AST_FCALL
&& child
->str
== str
)))
2572 AstNode
*wire
= child
->clone();
2573 wire
->str
= prefix
+ wire
->str
;
2575 wire
->is_input
= false;
2576 wire
->is_output
= false;
2577 current_ast_mod
->children
.push_back(wire
);
2578 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2580 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
2581 wire_id
->str
= wire
->str
;
2583 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
2585 AstNode
*arg
= children
[arg_count
++]->clone();
2586 AstNode
*assign
= child
->is_input
?
2587 new AstNode(AST_ASSIGN_EQ
, wire_id
->clone(), arg
) :
2588 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
->clone());
2589 assign
->children
[0]->was_checked
= true;
2591 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
2592 if (*it
!= current_block_child
)
2594 current_block
->children
.insert(it
, assign
);
2599 AstNode
*cell_arg
= new AstNode(AST_ARGUMENT
, wire_id
);
2600 cell_arg
->str
= child
->str
== str
? outport
: child
->str
;
2601 cell
->children
.push_back(cell_arg
);
2604 current_ast_mod
->children
.push_back(cell
);
2605 goto replace_fcall_with_id
;
2608 for (auto child
: decl
->children
)
2609 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
|| child
->type
== AST_ENUM_ITEM
)
2611 AstNode
*wire
= nullptr;
2613 if (wire_cache
.count(child
->str
))
2615 wire
= wire_cache
.at(child
->str
);
2616 if (wire
->children
.empty()) {
2617 for (auto c
: child
->children
)
2618 wire
->children
.push_back(c
->clone());
2619 } else if (!child
->children
.empty()) {
2620 while (child
->simplify(true, false, false, stage
, -1, false, false)) { }
2621 if (GetSize(child
->children
) == GetSize(wire
->children
)) {
2622 for (int i
= 0; i
< GetSize(child
->children
); i
++)
2623 if (*child
->children
.at(i
) != *wire
->children
.at(i
))
2624 goto tcall_incompatible_wires
;
2626 tcall_incompatible_wires
:
2627 log_file_error(filename
, linenum
, "Incompatible re-declaration of wire %s.\n", child
->str
.c_str());
2633 wire
= child
->clone();
2634 wire
->str
= prefix
+ wire
->str
;
2636 wire
->is_input
= false;
2637 wire
->is_output
= false;
2638 wire
->is_reg
= true;
2639 wire
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
2640 if (child
->type
== AST_ENUM_ITEM
)
2641 wire
->attributes
["\\enum_base_type"] = child
->attributes
["\\enum_base_type"];
2643 wire_cache
[child
->str
] = wire
;
2645 current_ast_mod
->children
.push_back(wire
);
2646 added_mod_children
.push_back(wire
);
2649 if (child
->type
== AST_WIRE
)
2650 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2652 replace_rules
[child
->str
] = wire
->str
;
2653 current_scope
[wire
->str
] = wire
;
2655 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
2657 AstNode
*arg
= children
[arg_count
++]->clone();
2658 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
2659 wire_id
->str
= wire
->str
;
2660 AstNode
*assign
= child
->is_input
?
2661 new AstNode(AST_ASSIGN_EQ
, wire_id
, arg
) :
2662 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
);
2663 assign
->children
[0]->was_checked
= true;
2664 if (child
->is_input
)
2665 new_stmts
.push_back(assign
);
2667 output_assignments
.push_back(assign
);
2671 for (auto child
: added_mod_children
) {
2672 child
->replace_ids(prefix
, replace_rules
);
2673 while (child
->simplify(true, false, false, 1, -1, false, false)) { }
2676 for (auto child
: decl
->children
)
2677 if (child
->type
!= AST_WIRE
&& child
->type
!= AST_MEMORY
&& child
->type
!= AST_PARAMETER
&& child
->type
!= AST_LOCALPARAM
)
2679 AstNode
*stmt
= child
->clone();
2680 stmt
->replace_ids(prefix
, replace_rules
);
2681 new_stmts
.push_back(stmt
);
2684 new_stmts
.insert(new_stmts
.end(), output_assignments
.begin(), output_assignments
.end());
2686 for (auto it
= current_block
->children
.begin(); ; it
++) {
2687 log_assert(it
!= current_block
->children
.end());
2688 if (*it
== current_block_child
) {
2689 current_block
->children
.insert(it
, new_stmts
.begin(), new_stmts
.end());
2694 replace_fcall_with_id
:
2695 if (type
== AST_FCALL
) {
2697 type
= AST_IDENTIFIER
;
2700 if (type
== AST_TCALL
)
2702 did_something
= true;
2705 replace_fcall_later
:;
2707 // perform const folding when activated
2711 std::vector
<RTLIL::State
> tmp_bits
;
2712 RTLIL::Const (*const_func
)(const RTLIL::Const
&, const RTLIL::Const
&, bool, bool, int);
2713 RTLIL::Const dummy_arg
;
2717 case AST_IDENTIFIER
:
2718 if (current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
|| current_scope
[str
]->type
== AST_ENUM_ITEM
)) {
2719 if (current_scope
[str
]->children
[0]->type
== AST_CONSTANT
) {
2720 if (children
.size() != 0 && children
[0]->type
== AST_RANGE
&& children
[0]->range_valid
) {
2721 std::vector
<RTLIL::State
> data
;
2722 bool param_upto
= current_scope
[str
]->range_valid
&& current_scope
[str
]->range_swapped
;
2723 int param_offset
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_right
: 0;
2724 int param_width
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_left
- current_scope
[str
]->range_right
+ 1 :
2725 GetSize(current_scope
[str
]->children
[0]->bits
);
2726 int tmp_range_left
= children
[0]->range_left
, tmp_range_right
= children
[0]->range_right
;
2728 tmp_range_left
= (param_width
+ 2*param_offset
) - children
[0]->range_right
- 1;
2729 tmp_range_right
= (param_width
+ 2*param_offset
) - children
[0]->range_left
- 1;
2731 for (int i
= tmp_range_right
; i
<= tmp_range_left
; i
++) {
2732 int index
= i
- param_offset
;
2733 if (0 <= index
&& index
< param_width
)
2734 data
.push_back(current_scope
[str
]->children
[0]->bits
[index
]);
2736 data
.push_back(RTLIL::State::Sx
);
2738 newNode
= mkconst_bits(data
, false);
2740 if (children
.size() == 0)
2741 newNode
= current_scope
[str
]->children
[0]->clone();
2743 if (current_scope
[str
]->children
[0]->isConst())
2744 newNode
= current_scope
[str
]->children
[0]->clone();
2746 else if (at_zero
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_WIRE
|| current_scope
[str
]->type
== AST_AUTOWIRE
)) {
2747 newNode
= mkconst_int(0, sign_hint
, width_hint
);
2751 if (children
[0]->type
== AST_CONSTANT
) {
2752 RTLIL::Const y
= RTLIL::const_not(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
2753 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2757 case AST_TO_UNSIGNED
:
2758 if (children
[0]->type
== AST_CONSTANT
) {
2759 RTLIL::Const y
= children
[0]->bitsAsConst(width_hint
, sign_hint
);
2760 newNode
= mkconst_bits(y
.bits
, type
== AST_TO_SIGNED
);
2763 if (0) { case AST_BIT_AND
: const_func
= RTLIL::const_and
; }
2764 if (0) { case AST_BIT_OR
: const_func
= RTLIL::const_or
; }
2765 if (0) { case AST_BIT_XOR
: const_func
= RTLIL::const_xor
; }
2766 if (0) { case AST_BIT_XNOR
: const_func
= RTLIL::const_xnor
; }
2767 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2768 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
2769 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
2770 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2773 if (0) { case AST_REDUCE_AND
: const_func
= RTLIL::const_reduce_and
; }
2774 if (0) { case AST_REDUCE_OR
: const_func
= RTLIL::const_reduce_or
; }
2775 if (0) { case AST_REDUCE_XOR
: const_func
= RTLIL::const_reduce_xor
; }
2776 if (0) { case AST_REDUCE_XNOR
: const_func
= RTLIL::const_reduce_xnor
; }
2777 if (0) { case AST_REDUCE_BOOL
: const_func
= RTLIL::const_reduce_bool
; }
2778 if (children
[0]->type
== AST_CONSTANT
) {
2779 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), dummy_arg
, false, false, -1);
2780 newNode
= mkconst_bits(y
.bits
, false);
2784 if (children
[0]->type
== AST_CONSTANT
) {
2785 RTLIL::Const y
= RTLIL::const_logic_not(RTLIL::Const(children
[0]->bits
), dummy_arg
, children
[0]->is_signed
, false, -1);
2786 newNode
= mkconst_bits(y
.bits
, false);
2788 if (children
[0]->isConst()) {
2789 newNode
= mkconst_int(children
[0]->asReal(sign_hint
) == 0, false, 1);
2792 if (0) { case AST_LOGIC_AND
: const_func
= RTLIL::const_logic_and
; }
2793 if (0) { case AST_LOGIC_OR
: const_func
= RTLIL::const_logic_or
; }
2794 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2795 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), RTLIL::Const(children
[1]->bits
),
2796 children
[0]->is_signed
, children
[1]->is_signed
, -1);
2797 newNode
= mkconst_bits(y
.bits
, false);
2799 if (children
[0]->isConst() && children
[1]->isConst()) {
2800 if (type
== AST_LOGIC_AND
)
2801 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) && (children
[1]->asReal(sign_hint
) != 0), false, 1);
2803 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) || (children
[1]->asReal(sign_hint
) != 0), false, 1);
2806 if (0) { case AST_SHIFT_LEFT
: const_func
= RTLIL::const_shl
; }
2807 if (0) { case AST_SHIFT_RIGHT
: const_func
= RTLIL::const_shr
; }
2808 if (0) { case AST_SHIFT_SLEFT
: const_func
= RTLIL::const_sshl
; }
2809 if (0) { case AST_SHIFT_SRIGHT
: const_func
= RTLIL::const_sshr
; }
2810 if (0) { case AST_POW
: const_func
= RTLIL::const_pow
; }
2811 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2812 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
2813 RTLIL::Const(children
[1]->bits
), sign_hint
, type
== AST_POW
? children
[1]->is_signed
: false, width_hint
);
2814 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2816 if (type
== AST_POW
&& children
[0]->isConst() && children
[1]->isConst()) {
2817 newNode
= new AstNode(AST_REALVALUE
);
2818 newNode
->realvalue
= pow(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
));
2821 if (0) { case AST_LT
: const_func
= RTLIL::const_lt
; }
2822 if (0) { case AST_LE
: const_func
= RTLIL::const_le
; }
2823 if (0) { case AST_EQ
: const_func
= RTLIL::const_eq
; }
2824 if (0) { case AST_NE
: const_func
= RTLIL::const_ne
; }
2825 if (0) { case AST_EQX
: const_func
= RTLIL::const_eqx
; }
2826 if (0) { case AST_NEX
: const_func
= RTLIL::const_nex
; }
2827 if (0) { case AST_GE
: const_func
= RTLIL::const_ge
; }
2828 if (0) { case AST_GT
: const_func
= RTLIL::const_gt
; }
2829 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2830 int cmp_width
= max(children
[0]->bits
.size(), children
[1]->bits
.size());
2831 bool cmp_signed
= children
[0]->is_signed
&& children
[1]->is_signed
;
2832 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(cmp_width
, cmp_signed
),
2833 children
[1]->bitsAsConst(cmp_width
, cmp_signed
), cmp_signed
, cmp_signed
, 1);
2834 newNode
= mkconst_bits(y
.bits
, false);
2836 if (children
[0]->isConst() && children
[1]->isConst()) {
2837 bool cmp_signed
= (children
[0]->type
== AST_REALVALUE
|| children
[0]->is_signed
) && (children
[1]->type
== AST_REALVALUE
|| children
[1]->is_signed
);
2839 case AST_LT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) < children
[1]->asReal(cmp_signed
), false, 1); break;
2840 case AST_LE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) <= children
[1]->asReal(cmp_signed
), false, 1); break;
2841 case AST_EQ
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
2842 case AST_NE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
2843 case AST_EQX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
2844 case AST_NEX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
2845 case AST_GE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) >= children
[1]->asReal(cmp_signed
), false, 1); break;
2846 case AST_GT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) > children
[1]->asReal(cmp_signed
), false, 1); break;
2847 default: log_abort();
2851 if (0) { case AST_ADD
: const_func
= RTLIL::const_add
; }
2852 if (0) { case AST_SUB
: const_func
= RTLIL::const_sub
; }
2853 if (0) { case AST_MUL
: const_func
= RTLIL::const_mul
; }
2854 if (0) { case AST_DIV
: const_func
= RTLIL::const_div
; }
2855 if (0) { case AST_MOD
: const_func
= RTLIL::const_mod
; }
2856 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2857 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
2858 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
2859 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2861 if (children
[0]->isConst() && children
[1]->isConst()) {
2862 newNode
= new AstNode(AST_REALVALUE
);
2864 case AST_ADD
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) + children
[1]->asReal(sign_hint
); break;
2865 case AST_SUB
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) - children
[1]->asReal(sign_hint
); break;
2866 case AST_MUL
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) * children
[1]->asReal(sign_hint
); break;
2867 case AST_DIV
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) / children
[1]->asReal(sign_hint
); break;
2868 case AST_MOD
: newNode
->realvalue
= fmod(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
)); break;
2869 default: log_abort();
2873 if (0) { case AST_POS
: const_func
= RTLIL::const_pos
; }
2874 if (0) { case AST_NEG
: const_func
= RTLIL::const_neg
; }
2875 if (children
[0]->type
== AST_CONSTANT
) {
2876 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
2877 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2879 if (children
[0]->isConst()) {
2880 newNode
= new AstNode(AST_REALVALUE
);
2881 if (type
== AST_POS
)
2882 newNode
->realvalue
= +children
[0]->asReal(sign_hint
);
2884 newNode
->realvalue
= -children
[0]->asReal(sign_hint
);
2888 if (children
[0]->isConst())
2890 bool found_sure_true
= false;
2891 bool found_maybe_true
= false;
2893 if (children
[0]->type
== AST_CONSTANT
)
2894 for (auto &bit
: children
[0]->bits
) {
2895 if (bit
== RTLIL::State::S1
)
2896 found_sure_true
= true;
2897 if (bit
> RTLIL::State::S1
)
2898 found_maybe_true
= true;
2901 found_sure_true
= children
[0]->asReal(sign_hint
) != 0;
2903 AstNode
*choice
= NULL
, *not_choice
= NULL
;
2904 if (found_sure_true
)
2905 choice
= children
[1], not_choice
= children
[2];
2906 else if (!found_maybe_true
)
2907 choice
= children
[2], not_choice
= children
[1];
2909 if (choice
!= NULL
) {
2910 if (choice
->type
== AST_CONSTANT
) {
2911 int other_width_hint
= width_hint
;
2912 bool other_sign_hint
= sign_hint
, other_real
= false;
2913 not_choice
->detectSignWidth(other_width_hint
, other_sign_hint
, &other_real
);
2915 newNode
= new AstNode(AST_REALVALUE
);
2916 choice
->detectSignWidth(width_hint
, sign_hint
);
2917 newNode
->realvalue
= choice
->asReal(sign_hint
);
2919 RTLIL::Const y
= choice
->bitsAsConst(width_hint
, sign_hint
);
2920 if (choice
->is_string
&& y
.bits
.size() % 8 == 0 && sign_hint
== false)
2921 newNode
= mkconst_str(y
.bits
);
2923 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2926 if (choice
->isConst()) {
2927 newNode
= choice
->clone();
2929 } else if (children
[1]->type
== AST_CONSTANT
&& children
[2]->type
== AST_CONSTANT
) {
2930 RTLIL::Const a
= children
[1]->bitsAsConst(width_hint
, sign_hint
);
2931 RTLIL::Const b
= children
[2]->bitsAsConst(width_hint
, sign_hint
);
2932 log_assert(a
.bits
.size() == b
.bits
.size());
2933 for (size_t i
= 0; i
< a
.bits
.size(); i
++)
2934 if (a
.bits
[i
] != b
.bits
[i
])
2935 a
.bits
[i
] = RTLIL::State::Sx
;
2936 newNode
= mkconst_bits(a
.bits
, sign_hint
);
2937 } else if (children
[1]->isConst() && children
[2]->isConst()) {
2938 newNode
= new AstNode(AST_REALVALUE
);
2939 if (children
[1]->asReal(sign_hint
) == children
[2]->asReal(sign_hint
))
2940 newNode
->realvalue
= children
[1]->asReal(sign_hint
);
2942 // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
2943 // the data type in question should be returned if the ?: is ambiguous. The
2944 // value in Table 7-1 for the 'real' type is 0.0.
2945 newNode
->realvalue
= 0.0;
2950 string_op
= !children
.empty();
2951 for (auto it
= children
.begin(); it
!= children
.end(); it
++) {
2952 if ((*it
)->type
!= AST_CONSTANT
)
2954 if (!(*it
)->is_string
)
2956 tmp_bits
.insert(tmp_bits
.end(), (*it
)->bits
.begin(), (*it
)->bits
.end());
2958 newNode
= string_op
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
2961 if (children
.at(0)->type
!= AST_CONSTANT
|| children
.at(1)->type
!= AST_CONSTANT
)
2963 for (int i
= 0; i
< children
[0]->bitsAsConst().as_int(); i
++)
2964 tmp_bits
.insert(tmp_bits
.end(), children
.at(1)->bits
.begin(), children
.at(1)->bits
.end());
2965 newNode
= children
.at(1)->is_string
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
2973 // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
2976 // fprintf(stderr, "----\n");
2977 // dumpAst(stderr, "- ");
2978 // newNode->dumpAst(stderr, "+ ");
2979 log_assert(newNode
!= NULL
);
2980 newNode
->filename
= filename
;
2981 newNode
->linenum
= linenum
;
2982 newNode
->cloneInto(this);
2984 did_something
= true;
2990 recursion_counter
--;
2991 return did_something
;
2994 static void replace_result_wire_name_in_function(AstNode
*node
, std::string
&from
, std::string
&to
)
2996 for (auto &it
: node
->children
)
2997 replace_result_wire_name_in_function(it
, from
, to
);
2998 if (node
->str
== from
)
3002 // replace a readmem[bh] TCALL ast node with a block of memory assignments
3003 AstNode
*AstNode::readmem(bool is_readmemh
, std::string mem_filename
, AstNode
*memory
, int start_addr
, int finish_addr
, bool unconditional_init
)
3005 int mem_width
, mem_size
, addr_bits
;
3006 memory
->meminfo(mem_width
, mem_size
, addr_bits
);
3008 AstNode
*block
= new AstNode(AST_BLOCK
);
3010 AstNode
*meminit
= nullptr;
3011 int next_meminit_cursor
=0;
3012 vector
<State
> meminit_bits
;
3016 f
.open(mem_filename
.c_str());
3017 yosys_input_files
.insert(mem_filename
);
3020 log_file_error(filename
, linenum
, "Can not open file `%s` for %s.\n", mem_filename
.c_str(), str
.c_str());
3022 log_assert(GetSize(memory
->children
) == 2 && memory
->children
[1]->type
== AST_RANGE
&& memory
->children
[1]->range_valid
);
3023 int range_left
= memory
->children
[1]->range_left
, range_right
= memory
->children
[1]->range_right
;
3024 int range_min
= min(range_left
, range_right
), range_max
= max(range_left
, range_right
);
3027 start_addr
= range_min
;
3029 if (finish_addr
< 0)
3030 finish_addr
= range_max
+ 1;
3032 bool in_comment
= false;
3033 int increment
= start_addr
<= finish_addr
? +1 : -1;
3034 int cursor
= start_addr
;
3038 std::string line
, token
;
3039 std::getline(f
, line
);
3041 for (int i
= 0; i
< GetSize(line
); i
++) {
3042 if (in_comment
&& line
.compare(i
, 2, "*/") == 0) {
3048 if (!in_comment
&& line
.compare(i
, 2, "/*") == 0)
3056 token
= next_token(line
, " \t\r\n");
3057 if (token
.empty() || token
.compare(0, 2, "//") == 0)
3060 if (token
[0] == '@') {
3061 token
= token
.substr(1);
3062 const char *nptr
= token
.c_str();
3064 cursor
= strtol(nptr
, &endptr
, 16);
3065 if (!*nptr
|| *endptr
)
3066 log_file_error(filename
, linenum
, "Can not parse address `%s` for %s.\n", nptr
, str
.c_str());
3070 AstNode
*value
= VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width
, is_readmemh
? 'h' : 'b') + token
);
3072 if (unconditional_init
)
3074 if (meminit
== nullptr || cursor
!= next_meminit_cursor
)
3076 if (meminit
!= nullptr) {
3077 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
3078 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
3081 meminit
= new AstNode(AST_MEMINIT
);
3082 meminit
->children
.push_back(AstNode::mkconst_int(cursor
, false));
3083 meminit
->children
.push_back(nullptr);
3084 meminit
->children
.push_back(nullptr);
3085 meminit
->str
= memory
->str
;
3086 meminit
->id2ast
= memory
;
3087 meminit_bits
.clear();
3090 current_ast_mod
->children
.push_back(meminit
);
3091 next_meminit_cursor
= cursor
;
3095 next_meminit_cursor
++;
3096 meminit_bits
.insert(meminit_bits
.end(), value
->bits
.begin(), value
->bits
.end());
3101 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
, false))), value
));
3102 block
->children
.back()->children
[0]->str
= memory
->str
;
3103 block
->children
.back()->children
[0]->id2ast
= memory
;
3104 block
->children
.back()->children
[0]->was_checked
= true;
3107 cursor
+= increment
;
3108 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
3112 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
3116 if (meminit
!= nullptr) {
3117 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
3118 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
3124 // annotate the names of all wires and other named objects in a generate block
3125 void AstNode::expand_genblock(std::string index_var
, std::string prefix
, std::map
<std::string
, std::string
> &name_map
)
3127 if (!index_var
.empty() && type
== AST_IDENTIFIER
&& str
== index_var
) {
3128 if (children
.empty()) {
3129 current_scope
[index_var
]->children
[0]->cloneInto(this);
3131 AstNode
*p
= new AstNode(AST_LOCALPARAM
, current_scope
[index_var
]->children
[0]->clone());
3132 p
->str
= stringf("$genval$%d", autoidx
++);
3133 current_ast_mod
->children
.push_back(p
);
3137 auto resolved
= current_scope
.at(index_var
);
3138 if (resolved
->range_valid
) {
3139 p
->range_left
= resolved
->range_left
;
3140 p
->range_right
= resolved
->range_right
;
3141 p
->range_swapped
= resolved
->range_swapped
;
3142 p
->range_valid
= resolved
->range_valid
;
3147 if ((type
== AST_IDENTIFIER
|| type
== AST_FCALL
|| type
== AST_TCALL
|| type
== AST_WIRETYPE
) && name_map
.count(str
) > 0)
3148 str
= name_map
[str
];
3150 std::map
<std::string
, std::string
> backup_name_map
;
3152 for (size_t i
= 0; i
< children
.size(); i
++) {
3153 AstNode
*child
= children
[i
];
3154 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
||
3155 child
->type
== AST_FUNCTION
|| child
->type
== AST_TASK
|| child
->type
== AST_CELL
|| child
->type
== AST_TYPEDEF
|| child
->type
== AST_ENUM_ITEM
) {
3156 if (backup_name_map
.size() == 0)
3157 backup_name_map
= name_map
;
3158 std::string new_name
= prefix
[0] == '\\' ? prefix
.substr(1) : prefix
;
3159 size_t pos
= child
->str
.rfind('.');
3160 if (pos
== std::string::npos
)
3161 pos
= child
->str
[0] == '\\' && prefix
[0] == '\\' ? 1 : 0;
3164 new_name
= child
->str
.substr(0, pos
) + new_name
+ child
->str
.substr(pos
);
3165 if (new_name
[0] != '$' && new_name
[0] != '\\')
3166 new_name
= prefix
[0] + new_name
;
3167 name_map
[child
->str
] = new_name
;
3168 if (child
->type
== AST_FUNCTION
)
3169 replace_result_wire_name_in_function(child
, child
->str
, new_name
);
3171 child
->str
= new_name
;
3172 current_scope
[new_name
] = child
;
3174 if (child
->type
== AST_ENUM
){
3175 current_scope
[child
->str
] = child
;
3176 for (auto enode
: child
->children
){
3177 log_assert(enode
->type
== AST_ENUM_ITEM
);
3178 if (backup_name_map
.size() == 0)
3179 backup_name_map
= name_map
;
3180 std::string new_name
= prefix
[0] == '\\' ? prefix
.substr(1) : prefix
;
3181 size_t pos
= enode
->str
.rfind('.');
3182 if (pos
== std::string::npos
)
3183 pos
= enode
->str
[0] == '\\' && prefix
[0] == '\\' ? 1 : 0;
3186 new_name
= enode
->str
.substr(0, pos
) + new_name
+ enode
->str
.substr(pos
);
3187 if (new_name
[0] != '$' && new_name
[0] != '\\')
3188 new_name
= prefix
[0] + new_name
;
3189 name_map
[enode
->str
] = new_name
;
3191 enode
->str
= new_name
;
3192 current_scope
[new_name
] = enode
;
3197 for (size_t i
= 0; i
< children
.size(); i
++) {
3198 AstNode
*child
= children
[i
];
3199 // AST_PREFIX member names should not be prefixed; a nested AST_PREFIX
3200 // still needs to recursed-into
3201 if (type
== AST_PREFIX
&& i
== 1 && child
->type
== AST_IDENTIFIER
)
3203 if (child
->type
!= AST_FUNCTION
&& child
->type
!= AST_TASK
)
3204 child
->expand_genblock(index_var
, prefix
, name_map
);
3208 if (backup_name_map
.size() > 0)
3209 name_map
.swap(backup_name_map
);
3212 // rename stuff (used when tasks of functions are instantiated)
3213 void AstNode::replace_ids(const std::string
&prefix
, const std::map
<std::string
, std::string
> &rules
)
3215 if (type
== AST_BLOCK
)
3217 std::map
<std::string
, std::string
> new_rules
= rules
;
3218 std::string new_prefix
= prefix
+ str
;
3220 for (auto child
: children
)
3221 if (child
->type
== AST_WIRE
) {
3222 new_rules
[child
->str
] = new_prefix
+ child
->str
;
3223 child
->str
= new_prefix
+ child
->str
;
3226 for (auto child
: children
)
3227 if (child
->type
!= AST_WIRE
)
3228 child
->replace_ids(new_prefix
, new_rules
);
3232 if (type
== AST_IDENTIFIER
&& rules
.count(str
) > 0)
3233 str
= rules
.at(str
);
3234 for (auto child
: children
)
3235 child
->replace_ids(prefix
, rules
);
3239 // helper function for mem2reg_as_needed_pass1
3240 static void mark_memories_assign_lhs_complex(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
3241 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, AstNode
*that
)
3243 for (auto &child
: that
->children
)
3244 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, child
);
3246 if (that
->type
== AST_IDENTIFIER
&& that
->id2ast
&& that
->id2ast
->type
== AST_MEMORY
) {
3247 AstNode
*mem
= that
->id2ast
;
3248 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_CMPLX_LHS
))
3249 mem2reg_places
[mem
].insert(stringf("%s:%d", that
->filename
.c_str(), that
->linenum
));
3250 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CMPLX_LHS
;
3254 // find memories that should be replaced by registers
3255 void AstNode::mem2reg_as_needed_pass1(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
3256 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, dict
<AstNode
*, uint32_t> &proc_flags
, uint32_t &flags
)
3258 uint32_t children_flags
= 0;
3259 int lhs_children_counter
= 0;
3261 if (type
== AST_TYPEDEF
)
3262 return; // don't touch content of typedefs
3264 if (type
== AST_ASSIGN
|| type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
)
3266 // mark all memories that are used in a complex expression on the left side of an assignment
3267 for (auto &lhs_child
: children
[0]->children
)
3268 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, lhs_child
);
3270 if (children
[0]->type
== AST_IDENTIFIER
&& children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
)
3272 AstNode
*mem
= children
[0]->id2ast
;
3274 // activate mem2reg if this is assigned in an async proc
3275 if (flags
& AstNode::MEM2REG_FL_ASYNC
) {
3276 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ASYNC
))
3277 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3278 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ASYNC
;
3281 // remember if this is assigned blocking (=)
3282 if (type
== AST_ASSIGN_EQ
) {
3283 if (!(proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
))
3284 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3285 proc_flags
[mem
] |= AstNode::MEM2REG_FL_EQ1
;
3288 // for proper (non-init) writes: remember if this is a constant index or not
3289 if ((flags
& MEM2REG_FL_INIT
) == 0) {
3290 if (children
[0]->children
.size() && children
[0]->children
[0]->type
== AST_RANGE
&& children
[0]->children
[0]->children
.size()) {
3291 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
)
3292 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CONST_LHS
;
3294 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_VAR_LHS
;
3298 // remember where this is
3299 if (flags
& MEM2REG_FL_INIT
) {
3300 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_INIT
))
3301 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3302 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_INIT
;
3304 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ELSE
))
3305 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3306 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ELSE
;
3310 lhs_children_counter
= 1;
3313 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
)
3315 AstNode
*mem
= id2ast
;
3317 // flag if used after blocking assignment (in same proc)
3318 if ((proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
) && !(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_EQ2
)) {
3319 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3320 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_EQ2
;
3324 // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg'
3325 if (type
== AST_MEMORY
&& (get_bool_attribute("\\mem2reg") || (flags
& AstNode::MEM2REG_FL_ALL
) || !is_reg
))
3326 mem2reg_candidates
[this] |= AstNode::MEM2REG_FL_FORCED
;
3328 if (type
== AST_MODULE
&& get_bool_attribute("\\mem2reg"))
3329 children_flags
|= AstNode::MEM2REG_FL_ALL
;
3331 dict
<AstNode
*, uint32_t> *proc_flags_p
= NULL
;
3333 if (type
== AST_ALWAYS
) {
3334 int count_edge_events
= 0;
3335 for (auto child
: children
)
3336 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
3337 count_edge_events
++;
3338 if (count_edge_events
!= 1)
3339 children_flags
|= AstNode::MEM2REG_FL_ASYNC
;
3340 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
3343 if (type
== AST_INITIAL
) {
3344 children_flags
|= AstNode::MEM2REG_FL_INIT
;
3345 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
3348 uint32_t backup_flags
= flags
;
3349 flags
|= children_flags
;
3350 log_assert((flags
& ~0x000000ff) == 0);
3352 for (auto child
: children
)
3354 if (lhs_children_counter
> 0) {
3355 lhs_children_counter
--;
3356 if (child
->children
.size() && child
->children
[0]->type
== AST_RANGE
&& child
->children
[0]->children
.size()) {
3357 for (auto c
: child
->children
[0]->children
) {
3359 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
3361 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
3366 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
3368 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
3371 flags
&= ~children_flags
| backup_flags
;
3375 for (auto it
: *proc_flags_p
)
3376 log_assert((it
.second
& ~0xff000000) == 0);
3378 delete proc_flags_p
;
3382 bool AstNode::mem2reg_check(pool
<AstNode
*> &mem2reg_set
)
3384 if (type
!= AST_IDENTIFIER
|| !id2ast
|| !mem2reg_set
.count(id2ast
))
3387 if (children
.empty() || children
[0]->type
!= AST_RANGE
|| GetSize(children
[0]->children
) != 1)
3388 log_file_error(filename
, linenum
, "Invalid array access.\n");
3393 void AstNode::mem2reg_remove(pool
<AstNode
*> &mem2reg_set
, vector
<AstNode
*> &delnodes
)
3395 log_assert(mem2reg_set
.count(this) == 0);
3397 if (mem2reg_set
.count(id2ast
))
3400 for (size_t i
= 0; i
< children
.size(); i
++) {
3401 if (mem2reg_set
.count(children
[i
]) > 0) {
3402 delnodes
.push_back(children
[i
]);
3403 children
.erase(children
.begin() + (i
--));
3405 children
[i
]->mem2reg_remove(mem2reg_set
, delnodes
);
3410 // actually replace memories with registers
3411 bool AstNode::mem2reg_as_needed_pass2(pool
<AstNode
*> &mem2reg_set
, AstNode
*mod
, AstNode
*block
, AstNode
*&async_block
)
3413 bool did_something
= false;
3415 if (type
== AST_BLOCK
)
3418 if (type
== AST_FUNCTION
|| type
== AST_TASK
)
3421 if (type
== AST_TYPEDEF
)
3424 if (type
== AST_MEMINIT
&& id2ast
&& mem2reg_set
.count(id2ast
))
3426 log_assert(children
[0]->type
== AST_CONSTANT
);
3427 log_assert(children
[1]->type
== AST_CONSTANT
);
3428 log_assert(children
[2]->type
== AST_CONSTANT
);
3430 int cursor
= children
[0]->asInt(false);
3431 Const data
= children
[1]->bitsAsConst();
3432 int length
= children
[2]->asInt(false);
3436 AstNode
*block
= new AstNode(AST_INITIAL
, new AstNode(AST_BLOCK
));
3437 mod
->children
.push_back(block
);
3438 block
= block
->children
[0];
3440 int wordsz
= GetSize(data
) / length
;
3442 for (int i
= 0; i
< length
; i
++) {
3443 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)));
3444 block
->children
.back()->children
[0]->str
= str
;
3445 block
->children
.back()->children
[0]->id2ast
= id2ast
;
3446 block
->children
.back()->children
[0]->was_checked
= true;
3450 AstNode
*newNode
= new AstNode(AST_NONE
);
3451 newNode
->cloneInto(this);
3454 did_something
= true;
3457 if (type
== AST_ASSIGN
&& block
== NULL
&& children
[0]->mem2reg_check(mem2reg_set
))
3459 if (async_block
== NULL
) {
3460 async_block
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
3461 mod
->children
.push_back(async_block
);
3464 AstNode
*newNode
= clone();
3465 newNode
->type
= AST_ASSIGN_EQ
;
3466 newNode
->children
[0]->was_checked
= true;
3467 async_block
->children
[0]->children
.push_back(newNode
);
3469 newNode
= new AstNode(AST_NONE
);
3470 newNode
->cloneInto(this);
3473 did_something
= true;
3476 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->mem2reg_check(mem2reg_set
) &&
3477 children
[0]->children
[0]->children
[0]->type
!= AST_CONSTANT
)
3479 std::stringstream sstr
;
3480 sstr
<< "$mem2reg_wr$" << children
[0]->str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
3481 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
3483 int mem_width
, mem_size
, addr_bits
;
3484 bool mem_signed
= children
[0]->id2ast
->is_signed
;
3485 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
3487 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
3488 wire_addr
->str
= id_addr
;
3489 wire_addr
->is_reg
= true;
3490 wire_addr
->was_checked
= true;
3491 wire_addr
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3492 mod
->children
.push_back(wire_addr
);
3493 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
3495 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
3496 wire_data
->str
= id_data
;
3497 wire_data
->is_reg
= true;
3498 wire_data
->was_checked
= true;
3499 wire_data
->is_signed
= mem_signed
;
3500 wire_data
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3501 mod
->children
.push_back(wire_data
);
3502 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
3504 log_assert(block
!= NULL
);
3505 size_t assign_idx
= 0;
3506 while (assign_idx
< block
->children
.size() && block
->children
[assign_idx
] != this)
3508 log_assert(assign_idx
< block
->children
.size());
3510 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
3511 assign_addr
->children
[0]->str
= id_addr
;
3512 assign_addr
->children
[0]->was_checked
= true;
3513 block
->children
.insert(block
->children
.begin()+assign_idx
+1, assign_addr
);
3515 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
3516 case_node
->children
[0]->str
= id_addr
;
3517 for (int i
= 0; i
< mem_size
; i
++) {
3518 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->children
[0]->integer
) != i
)
3520 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
3521 AstNode
*assign_reg
= new AstNode(type
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
3522 if (children
[0]->children
.size() == 2)
3523 assign_reg
->children
[0]->children
.push_back(children
[0]->children
[1]->clone());
3524 assign_reg
->children
[0]->str
= stringf("%s[%d]", children
[0]->str
.c_str(), i
);
3525 assign_reg
->children
[1]->str
= id_data
;
3526 cond_node
->children
[1]->children
.push_back(assign_reg
);
3527 case_node
->children
.push_back(cond_node
);
3529 block
->children
.insert(block
->children
.begin()+assign_idx
+2, case_node
);
3531 children
[0]->delete_children();
3532 children
[0]->range_valid
= false;
3533 children
[0]->id2ast
= NULL
;
3534 children
[0]->str
= id_data
;
3535 type
= AST_ASSIGN_EQ
;
3536 children
[0]->was_checked
= true;
3538 did_something
= true;
3541 if (mem2reg_check(mem2reg_set
))
3543 AstNode
*bit_part_sel
= NULL
;
3544 if (children
.size() == 2)
3545 bit_part_sel
= children
[1]->clone();
3547 if (children
[0]->children
[0]->type
== AST_CONSTANT
)
3549 int id
= children
[0]->children
[0]->integer
;
3550 str
= stringf("%s[%d]", str
.c_str(), id
);
3553 range_valid
= false;
3558 std::stringstream sstr
;
3559 sstr
<< "$mem2reg_rd$" << str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
3560 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
3562 int mem_width
, mem_size
, addr_bits
;
3563 bool mem_signed
= id2ast
->is_signed
;
3564 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
3566 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
3567 wire_addr
->str
= id_addr
;
3568 wire_addr
->is_reg
= true;
3569 wire_addr
->was_checked
= true;
3571 wire_addr
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3572 mod
->children
.push_back(wire_addr
);
3573 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
3575 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
3576 wire_data
->str
= id_data
;
3577 wire_data
->is_reg
= true;
3578 wire_data
->was_checked
= true;
3579 wire_data
->is_signed
= mem_signed
;
3581 wire_data
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3582 mod
->children
.push_back(wire_data
);
3583 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
3585 AstNode
*assign_addr
= new AstNode(block
? AST_ASSIGN_EQ
: AST_ASSIGN
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->clone());
3586 assign_addr
->children
[0]->str
= id_addr
;
3587 assign_addr
->children
[0]->was_checked
= true;
3589 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
3590 case_node
->children
[0]->str
= id_addr
;
3592 for (int i
= 0; i
< mem_size
; i
++) {
3593 if (children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->integer
) != i
)
3595 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
3596 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
3597 assign_reg
->children
[0]->str
= id_data
;
3598 assign_reg
->children
[0]->was_checked
= true;
3599 assign_reg
->children
[1]->str
= stringf("%s[%d]", str
.c_str(), i
);
3600 cond_node
->children
[1]->children
.push_back(assign_reg
);
3601 case_node
->children
.push_back(cond_node
);
3604 std::vector
<RTLIL::State
> x_bits
;
3605 for (int i
= 0; i
< mem_width
; i
++)
3606 x_bits
.push_back(RTLIL::State::Sx
);
3608 AstNode
*cond_node
= new AstNode(AST_COND
, new AstNode(AST_DEFAULT
), new AstNode(AST_BLOCK
));
3609 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), AstNode::mkconst_bits(x_bits
, false));
3610 assign_reg
->children
[0]->str
= id_data
;
3611 assign_reg
->children
[0]->was_checked
= true;
3612 cond_node
->children
[1]->children
.push_back(assign_reg
);
3613 case_node
->children
.push_back(cond_node
);
3617 size_t assign_idx
= 0;
3618 while (assign_idx
< block
->children
.size() && !block
->children
[assign_idx
]->contains(this))
3620 log_assert(assign_idx
< block
->children
.size());
3621 block
->children
.insert(block
->children
.begin()+assign_idx
, case_node
);
3622 block
->children
.insert(block
->children
.begin()+assign_idx
, assign_addr
);
3626 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
3627 proc
->children
[0]->children
.push_back(case_node
);
3628 mod
->children
.push_back(proc
);
3629 mod
->children
.push_back(assign_addr
);
3633 range_valid
= false;
3639 children
.push_back(bit_part_sel
);
3641 did_something
= true;
3644 log_assert(id2ast
== NULL
|| mem2reg_set
.count(id2ast
) == 0);
3646 auto children_list
= children
;
3647 for (size_t i
= 0; i
< children_list
.size(); i
++)
3648 if (children_list
[i
]->mem2reg_as_needed_pass2(mem2reg_set
, mod
, block
, async_block
))
3649 did_something
= true;
3651 return did_something
;
3654 // calculate memory dimensions
3655 void AstNode::meminfo(int &mem_width
, int &mem_size
, int &addr_bits
)
3657 log_assert(type
== AST_MEMORY
);
3659 mem_width
= children
[0]->range_left
- children
[0]->range_right
+ 1;
3660 mem_size
= children
[1]->range_left
- children
[1]->range_right
;
3664 mem_size
+= min(children
[1]->range_left
, children
[1]->range_right
) + 1;
3667 while ((1 << addr_bits
) < mem_size
)
3671 bool AstNode::has_const_only_constructs(bool &recommend_const_eval
)
3673 if (type
== AST_FOR
)
3674 recommend_const_eval
= true;
3675 if (type
== AST_WHILE
|| type
== AST_REPEAT
)
3677 if (type
== AST_FCALL
&& current_scope
.count(str
))
3678 if (current_scope
[str
]->has_const_only_constructs(recommend_const_eval
))
3680 for (auto child
: children
)
3681 if (child
->AstNode::has_const_only_constructs(recommend_const_eval
))
3686 bool AstNode::is_simple_const_expr()
3688 if (type
== AST_IDENTIFIER
)
3690 for (auto child
: children
)
3691 if (!child
->is_simple_const_expr())
3696 // helper function for AstNode::eval_const_function()
3697 void AstNode::replace_variables(std::map
<std::string
, AstNode::varinfo_t
> &variables
, AstNode
*fcall
)
3699 if (type
== AST_IDENTIFIER
&& variables
.count(str
)) {
3700 int offset
= variables
.at(str
).offset
, width
= variables
.at(str
).val
.bits
.size();
3701 if (!children
.empty()) {
3702 if (children
.size() != 1 || children
.at(0)->type
!= AST_RANGE
)
3703 log_file_error(filename
, linenum
, "Memory access in constant function is not supported\n%s:%d: ...called from here.\n",
3704 fcall
->filename
.c_str(), fcall
->linenum
);
3705 children
.at(0)->replace_variables(variables
, fcall
);
3706 while (simplify(true, false, false, 1, -1, false, true)) { }
3707 if (!children
.at(0)->range_valid
)
3708 log_file_error(filename
, linenum
, "Non-constant range\n%s:%d: ... called from here.\n",
3709 fcall
->filename
.c_str(), fcall
->linenum
);
3710 offset
= min(children
.at(0)->range_left
, children
.at(0)->range_right
);
3711 width
= min(std::abs(children
.at(0)->range_left
- children
.at(0)->range_right
) + 1, width
);
3713 offset
-= variables
.at(str
).offset
;
3714 std::vector
<RTLIL::State
> &var_bits
= variables
.at(str
).val
.bits
;
3715 std::vector
<RTLIL::State
> new_bits(var_bits
.begin() + offset
, var_bits
.begin() + offset
+ width
);
3716 AstNode
*newNode
= mkconst_bits(new_bits
, variables
.at(str
).is_signed
);
3717 newNode
->cloneInto(this);
3722 for (auto &child
: children
)
3723 child
->replace_variables(variables
, fcall
);
3726 // evaluate functions with all-const arguments
3727 AstNode
*AstNode::eval_const_function(AstNode
*fcall
)
3729 std::map
<std::string
, AstNode
*> backup_scope
;
3730 std::map
<std::string
, AstNode::varinfo_t
> variables
;
3731 AstNode
*block
= new AstNode(AST_BLOCK
);
3734 for (auto child
: children
)
3736 if (child
->type
== AST_WIRE
)
3738 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
3739 if (!child
->range_valid
)
3740 log_file_error(child
->filename
, child
->linenum
, "Can't determine size of variable %s\n%s:%d: ... called from here.\n",
3741 child
->str
.c_str(), fcall
->filename
.c_str(), fcall
->linenum
);
3742 variables
[child
->str
].val
= RTLIL::Const(RTLIL::State::Sx
, abs(child
->range_left
- child
->range_right
)+1);
3743 variables
[child
->str
].offset
= min(child
->range_left
, child
->range_right
);
3744 variables
[child
->str
].is_signed
= child
->is_signed
;
3745 if (child
->is_input
&& argidx
< fcall
->children
.size())
3746 variables
[child
->str
].val
= fcall
->children
.at(argidx
++)->bitsAsConst(variables
[child
->str
].val
.bits
.size());
3747 backup_scope
[child
->str
] = current_scope
[child
->str
];
3748 current_scope
[child
->str
] = child
;
3752 block
->children
.push_back(child
->clone());
3755 log_assert(variables
.count(str
) != 0);
3757 while (!block
->children
.empty())
3759 AstNode
*stmt
= block
->children
.front();
3762 log("-----------------------------------\n");
3763 for (auto &it
: variables
)
3764 log("%20s %40s\n", it
.first
.c_str(), log_signal(it
.second
.val
));
3765 stmt
->dumpAst(NULL
, "stmt> ");
3768 if (stmt
->type
== AST_ASSIGN_EQ
)
3770 if (stmt
->children
.at(0)->type
== AST_IDENTIFIER
&& stmt
->children
.at(0)->children
.size() != 0 &&
3771 stmt
->children
.at(0)->children
.at(0)->type
== AST_RANGE
)
3772 stmt
->children
.at(0)->children
.at(0)->replace_variables(variables
, fcall
);
3773 stmt
->children
.at(1)->replace_variables(variables
, fcall
);
3774 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
3776 if (stmt
->type
!= AST_ASSIGN_EQ
)
3779 if (stmt
->children
.at(1)->type
!= AST_CONSTANT
)
3780 log_file_error(stmt
->filename
, stmt
->linenum
, "Non-constant expression in constant function\n%s:%d: ... called from here. X\n",
3781 fcall
->filename
.c_str(), fcall
->linenum
);
3783 if (stmt
->children
.at(0)->type
!= AST_IDENTIFIER
)
3784 log_file_error(stmt
->filename
, stmt
->linenum
, "Unsupported composite left hand side in constant function\n%s:%d: ... called from here.\n",
3785 fcall
->filename
.c_str(), fcall
->linenum
);
3787 if (!variables
.count(stmt
->children
.at(0)->str
))
3788 log_file_error(stmt
->filename
, stmt
->linenum
, "Assignment to non-local variable in constant function\n%s:%d: ... called from here.\n",
3789 fcall
->filename
.c_str(), fcall
->linenum
);
3791 if (stmt
->children
.at(0)->children
.empty()) {
3792 variables
[stmt
->children
.at(0)->str
].val
= stmt
->children
.at(1)->bitsAsConst(variables
[stmt
->children
.at(0)->str
].val
.bits
.size());
3794 AstNode
*range
= stmt
->children
.at(0)->children
.at(0);
3795 if (!range
->range_valid
)
3796 log_file_error(range
->filename
, range
->linenum
, "Non-constant range\n%s:%d: ... called from here.\n",
3797 fcall
->filename
.c_str(), fcall
->linenum
);
3798 int offset
= min(range
->range_left
, range
->range_right
);
3799 int width
= std::abs(range
->range_left
- range
->range_right
) + 1;
3800 varinfo_t
&v
= variables
[stmt
->children
.at(0)->str
];
3801 RTLIL::Const r
= stmt
->children
.at(1)->bitsAsConst(v
.val
.bits
.size());
3802 for (int i
= 0; i
< width
; i
++)
3803 v
.val
.bits
.at(i
+offset
-v
.offset
) = r
.bits
.at(i
);
3806 delete block
->children
.front();
3807 block
->children
.erase(block
->children
.begin());
3811 if (stmt
->type
== AST_FOR
)
3813 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(0));
3814 stmt
->children
.at(3)->children
.push_back(stmt
->children
.at(2));
3815 stmt
->children
.erase(stmt
->children
.begin() + 2);
3816 stmt
->children
.erase(stmt
->children
.begin());
3817 stmt
->type
= AST_WHILE
;
3821 if (stmt
->type
== AST_WHILE
)
3823 AstNode
*cond
= stmt
->children
.at(0)->clone();
3824 cond
->replace_variables(variables
, fcall
);
3825 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
3827 if (cond
->type
!= AST_CONSTANT
)
3828 log_file_error(stmt
->filename
, stmt
->linenum
, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
3829 fcall
->filename
.c_str(), fcall
->linenum
);
3831 if (cond
->asBool()) {
3832 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
3834 delete block
->children
.front();
3835 block
->children
.erase(block
->children
.begin());
3842 if (stmt
->type
== AST_REPEAT
)
3844 AstNode
*num
= stmt
->children
.at(0)->clone();
3845 num
->replace_variables(variables
, fcall
);
3846 while (num
->simplify(true, false, false, 1, -1, false, true)) { }
3848 if (num
->type
!= AST_CONSTANT
)
3849 log_file_error(stmt
->filename
, stmt
->linenum
, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
3850 fcall
->filename
.c_str(), fcall
->linenum
);
3852 block
->children
.erase(block
->children
.begin());
3853 for (int i
= 0; i
< num
->bitsAsConst().as_int(); i
++)
3854 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
3861 if (stmt
->type
== AST_CASE
)
3863 AstNode
*expr
= stmt
->children
.at(0)->clone();
3864 expr
->replace_variables(variables
, fcall
);
3865 while (expr
->simplify(true, false, false, 1, -1, false, true)) { }
3867 AstNode
*sel_case
= NULL
;
3868 for (size_t i
= 1; i
< stmt
->children
.size(); i
++)
3870 bool found_match
= false;
3871 log_assert(stmt
->children
.at(i
)->type
== AST_COND
|| stmt
->children
.at(i
)->type
== AST_CONDX
|| stmt
->children
.at(i
)->type
== AST_CONDZ
);
3873 if (stmt
->children
.at(i
)->children
.front()->type
== AST_DEFAULT
) {
3874 sel_case
= stmt
->children
.at(i
)->children
.back();
3878 for (size_t j
= 0; j
+1 < stmt
->children
.at(i
)->children
.size() && !found_match
; j
++)
3880 AstNode
*cond
= stmt
->children
.at(i
)->children
.at(j
)->clone();
3881 cond
->replace_variables(variables
, fcall
);
3883 cond
= new AstNode(AST_EQ
, expr
->clone(), cond
);
3884 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
3886 if (cond
->type
!= AST_CONSTANT
)
3887 log_file_error(stmt
->filename
, stmt
->linenum
, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
3888 fcall
->filename
.c_str(), fcall
->linenum
);
3890 found_match
= cond
->asBool();
3895 sel_case
= stmt
->children
.at(i
)->children
.back();
3900 block
->children
.erase(block
->children
.begin());
3902 block
->children
.insert(block
->children
.begin(), sel_case
->clone());
3908 if (stmt
->type
== AST_BLOCK
)
3910 block
->children
.erase(block
->children
.begin());
3911 block
->children
.insert(block
->children
.begin(), stmt
->children
.begin(), stmt
->children
.end());
3912 stmt
->children
.clear();
3917 log_file_error(stmt
->filename
, stmt
->linenum
, "Unsupported language construct in constant function\n%s:%d: ... called from here.\n",
3918 fcall
->filename
.c_str(), fcall
->linenum
);
3924 for (auto &it
: backup_scope
)
3925 if (it
.second
== NULL
)
3926 current_scope
.erase(it
.first
);
3928 current_scope
[it
.first
] = it
.second
;
3930 return AstNode::mkconst_bits(variables
.at(str
).val
.bits
, variables
.at(str
).is_signed
);
3933 void AstNode::allocateDefaultEnumValues()
3935 log_assert(type
==AST_ENUM
);
3936 int last_enum_int
= -1;
3937 for (auto node
: children
) {
3938 log_assert(node
->type
==AST_ENUM_ITEM
);
3939 node
->attributes
["\\enum_base_type"] = mkconst_str(str
);
3940 for (size_t i
= 0; i
< node
->children
.size(); i
++) {
3941 switch (node
->children
[i
]->type
) {
3943 // replace with auto-incremented constant
3944 delete node
->children
[i
];
3945 node
->children
[i
] = AstNode::mkconst_int(++last_enum_int
, true);
3948 // explicit constant (or folded expression)
3949 // TODO: can't extend 'x or 'z item
3950 last_enum_int
= node
->children
[i
]->integer
;
3956 // TODO: range check