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 subsitited 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 AstNode
*newNode
= NULL
;
53 bool did_something
= false;
54 static pair
<string
, int> last_blocking_assignment_warn
;
57 log("-------------\n");
58 log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
59 int(const_fold
), int(at_zero
), int(in_lvalue
), int(stage
), int(width_hint
), int(sign_hint
), int(in_param
));
65 log_assert(type
== AST_MODULE
);
66 last_blocking_assignment_warn
= pair
<string
, int>();
68 while (simplify(const_fold
, at_zero
, in_lvalue
, 1, width_hint
, sign_hint
, in_param
)) { }
70 if (!flag_nomem2reg
&& !get_bool_attribute("\\nomem2reg"))
72 dict
<AstNode
*, pool
<std::string
>> mem2reg_places
;
73 dict
<AstNode
*, uint32_t> mem2reg_candidates
, dummy_proc_flags
;
74 uint32_t flags
= flag_mem2reg
? AstNode::MEM2REG_FL_ALL
: 0;
75 mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, dummy_proc_flags
, flags
);
77 pool
<AstNode
*> mem2reg_set
;
78 for (auto &it
: mem2reg_candidates
)
80 AstNode
*mem
= it
.first
;
81 uint32_t memflags
= it
.second
;
82 log_assert((memflags
& ~0x00ffff00) == 0);
84 if (mem
->get_bool_attribute("\\nomem2reg"))
87 if (memflags
& AstNode::MEM2REG_FL_FORCED
)
90 if (memflags
& AstNode::MEM2REG_FL_EQ2
)
91 goto verbose_activate
;
93 if (memflags
& AstNode::MEM2REG_FL_SET_ASYNC
)
94 goto verbose_activate
;
96 if ((memflags
& AstNode::MEM2REG_FL_SET_INIT
) && (memflags
& AstNode::MEM2REG_FL_SET_ELSE
))
97 goto verbose_activate
;
99 if (memflags
& AstNode::MEM2REG_FL_CMPLX_LHS
)
100 goto verbose_activate
;
102 // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
106 if (mem2reg_set
.count(mem
) == 0) {
107 std::string message
= stringf("Replacing memory %s with list of registers.", mem
->str
.c_str());
108 bool first_element
= true;
109 for (auto &place
: mem2reg_places
[it
.first
]) {
110 message
+= stringf("%s%s", first_element
? " See " : ", ", place
.c_str());
111 first_element
= false;
113 log_warning("%s\n", message
.c_str());
117 // log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
118 mem2reg_set
.insert(mem
);
121 for (auto node
: mem2reg_set
)
123 int mem_width
, mem_size
, addr_bits
;
124 node
->meminfo(mem_width
, mem_size
, addr_bits
);
126 for (int i
= 0; i
< mem_size
; i
++) {
127 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
128 mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
129 reg
->str
= stringf("%s[%d]", node
->str
.c_str(), i
);
131 reg
->is_signed
= node
->is_signed
;
132 children
.push_back(reg
);
133 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
137 mem2reg_as_needed_pass2(mem2reg_set
, this, NULL
);
139 for (size_t i
= 0; i
< children
.size(); i
++) {
140 if (mem2reg_set
.count(children
[i
]) > 0) {
142 children
.erase(children
.begin() + (i
--));
147 while (simplify(const_fold
, at_zero
, in_lvalue
, 2, width_hint
, sign_hint
, in_param
)) { }
151 current_filename
= filename
;
152 set_line_num(linenum
);
154 // we do not look inside a task or function
155 // (but as soon as a task of function is instanciated we process the generated AST as usual)
156 if (type
== AST_FUNCTION
|| type
== AST_TASK
)
159 // deactivate all calls to non-synthesis system taks
160 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && (str
== "$display" || str
== "$strobe" || str
== "$monitor" || str
== "$time" || str
== "$stop" || str
== "$finish" ||
161 str
== "$dumpfile" || str
== "$dumpvars" || str
== "$dumpon" || str
== "$dumpoff" || str
== "$dumpall")) {
162 log_warning("Ignoring call to system %s %s at %s:%d.\n", type
== AST_FCALL
? "function" : "task", str
.c_str(), filename
.c_str(), linenum
);
167 // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
168 if (type
== AST_WIRE
|| type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_RANGE
|| type
== AST_PREFIX
)
170 if (type
== AST_IDENTIFIER
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
))
173 // in certain cases a function must be evaluated constant. this is what in_param controls.
174 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_PREFIX
)
177 std::map
<std::string
, AstNode
*> backup_scope
;
179 // create name resolution entries for all objects with names
180 // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
181 if (type
== AST_MODULE
) {
182 current_scope
.clear();
183 std::map
<std::string
, AstNode
*> this_wire_scope
;
184 for (size_t i
= 0; i
< children
.size(); i
++) {
185 AstNode
*node
= children
[i
];
186 if (node
->type
== AST_WIRE
) {
187 if (this_wire_scope
.count(node
->str
) > 0) {
188 AstNode
*first_node
= this_wire_scope
[node
->str
];
189 if (!node
->is_input
&& !node
->is_output
&& node
->is_reg
&& node
->children
.size() == 0)
190 goto wires_are_compatible
;
191 if (first_node
->children
.size() == 0 && node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
192 AstNode
*r
= node
->children
[0];
193 if (r
->range_valid
&& r
->range_left
== 0 && r
->range_right
== 0) {
195 node
->children
.pop_back();
198 if (first_node
->children
.size() != node
->children
.size())
199 goto wires_are_incompatible
;
200 for (size_t j
= 0; j
< node
->children
.size(); j
++) {
201 AstNode
*n1
= first_node
->children
[j
], *n2
= node
->children
[j
];
202 if (n1
->type
== AST_RANGE
&& n2
->type
== AST_RANGE
&& n1
->range_valid
&& n2
->range_valid
) {
203 if (n1
->range_left
!= n2
->range_left
)
204 goto wires_are_incompatible
;
205 if (n1
->range_right
!= n2
->range_right
)
206 goto wires_are_incompatible
;
207 } else if (*n1
!= *n2
)
208 goto wires_are_incompatible
;
210 if (first_node
->range_left
!= node
->range_left
)
211 goto wires_are_incompatible
;
212 if (first_node
->range_right
!= node
->range_right
)
213 goto wires_are_incompatible
;
214 if (first_node
->port_id
== 0 && (node
->is_input
|| node
->is_output
))
215 goto wires_are_incompatible
;
216 wires_are_compatible
:
218 first_node
->is_input
= true;
220 first_node
->is_output
= true;
222 first_node
->is_reg
= true;
224 first_node
->is_signed
= true;
225 for (auto &it
: node
->attributes
) {
226 if (first_node
->attributes
.count(it
.first
) > 0)
227 delete first_node
->attributes
[it
.first
];
228 first_node
->attributes
[it
.first
] = it
.second
->clone();
230 children
.erase(children
.begin()+(i
--));
231 did_something
= true;
234 wires_are_incompatible
:
236 log_error("Incompatible re-declaration of wire %s at %s:%d.\n", node
->str
.c_str(), filename
.c_str(), linenum
);
239 this_wire_scope
[node
->str
] = node
;
241 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
242 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
|| node
->type
== AST_CELL
) {
243 backup_scope
[node
->str
] = current_scope
[node
->str
];
244 current_scope
[node
->str
] = node
;
247 for (size_t i
= 0; i
< children
.size(); i
++) {
248 AstNode
*node
= children
[i
];
249 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
)
250 while (node
->simplify(true, false, false, 1, -1, false, node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
))
251 did_something
= true;
255 auto backup_current_block
= current_block
;
256 auto backup_current_block_child
= current_block_child
;
257 auto backup_current_top_block
= current_top_block
;
259 int backup_width_hint
= width_hint
;
260 bool backup_sign_hint
= sign_hint
;
262 bool detect_width_simple
= false;
263 bool child_0_is_self_determined
= false;
264 bool child_1_is_self_determined
= false;
265 bool child_2_is_self_determined
= false;
266 bool children_are_self_determined
= false;
267 bool reset_width_after_children
= false;
274 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, true, stage
, -1, false, in_param
) == true)
275 did_something
= true;
276 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
) == true)
277 did_something
= true;
278 children
[0]->detectSignWidth(backup_width_hint
, backup_sign_hint
);
279 children
[1]->detectSignWidth(width_hint
, sign_hint
);
280 width_hint
= std::max(width_hint
, backup_width_hint
);
281 child_0_is_self_determined
= true;
286 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, true) == true)
287 did_something
= true;
288 children
[0]->detectSignWidth(width_hint
, sign_hint
);
289 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
290 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, true) == true)
291 did_something
= true;
292 if (!children
[1]->range_valid
)
293 log_error("Non-constant width range on parameter decl at %s:%d.\n", filename
.c_str(), linenum
);
294 width_hint
= std::max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
300 case AST_TO_UNSIGNED
:
306 case AST_REDUCE_XNOR
:
307 case AST_REDUCE_BOOL
:
308 detect_width_simple
= true;
309 children_are_self_determined
= true;
324 detect_width_simple
= true;
328 case AST_SHIFT_RIGHT
:
329 case AST_SHIFT_SLEFT
:
330 case AST_SHIFT_SRIGHT
:
332 detect_width_simple
= true;
333 child_1_is_self_determined
= true;
346 for (auto child
: children
) {
347 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
348 did_something
= true;
349 child
->detectSignWidthWorker(width_hint
, sign_hint
);
351 reset_width_after_children
= true;
357 detect_width_simple
= true;
358 children_are_self_determined
= true;
362 detect_width_simple
= true;
363 child_0_is_self_determined
= true;
367 detect_width_simple
= true;
368 children_are_self_determined
= true;
376 if (detect_width_simple
&& width_hint
< 0) {
377 if (type
== AST_REPLICATE
)
378 while (children
[0]->simplify(true, false, in_lvalue
, stage
, -1, false, true) == true)
379 did_something
= true;
380 for (auto child
: children
)
381 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
382 did_something
= true;
383 detectSignWidth(width_hint
, sign_hint
);
386 if (type
== AST_TERNARY
) {
387 int width_hint_left
, width_hint_right
;
388 bool sign_hint_left
, sign_hint_right
;
389 bool found_real_left
, found_real_right
;
390 children
[1]->detectSignWidth(width_hint_left
, sign_hint_left
, &found_real_left
);
391 children
[2]->detectSignWidth(width_hint_right
, sign_hint_right
, &found_real_right
);
392 if (found_real_left
|| found_real_right
) {
393 child_1_is_self_determined
= true;
394 child_2_is_self_determined
= true;
398 if (const_fold
&& type
== AST_CASE
)
400 while (children
[0]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
401 if (children
[0]->type
== AST_CONSTANT
&& children
[0]->bits_only_01()) {
402 std::vector
<AstNode
*> new_children
;
403 new_children
.push_back(children
[0]);
404 for (int i
= 1; i
< GetSize(children
); i
++) {
405 AstNode
*child
= children
[i
];
406 log_assert(child
->type
== AST_COND
);
407 for (auto v
: child
->children
) {
408 if (v
->type
== AST_DEFAULT
)
409 goto keep_const_cond
;
410 if (v
->type
== AST_BLOCK
)
412 while (v
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
413 if (v
->type
== AST_CONSTANT
&& v
->bits_only_01()) {
414 if (v
->bits
== children
[0]->bits
) {
415 while (i
+1 < GetSize(children
))
416 delete children
[++i
];
417 goto keep_const_cond
;
421 goto keep_const_cond
;
425 new_children
.push_back(child
);
429 new_children
.swap(children
);
433 // simplify all children first
434 // (iterate by index as e.g. auto wires can add new children in the process)
435 for (size_t i
= 0; i
< children
.size(); i
++) {
436 bool did_something_here
= true;
437 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && i
>= 3)
439 if ((type
== AST_GENIF
|| type
== AST_GENCASE
) && i
>= 1)
441 if (type
== AST_GENBLOCK
)
443 if (type
== AST_BLOCK
&& !str
.empty())
445 if (type
== AST_PREFIX
&& i
>= 1)
447 while (did_something_here
&& i
< children
.size()) {
448 bool const_fold_here
= const_fold
, in_lvalue_here
= in_lvalue
;
449 int width_hint_here
= width_hint
;
450 bool sign_hint_here
= sign_hint
;
451 bool in_param_here
= in_param
;
452 if (i
== 0 && (type
== AST_REPLICATE
|| type
== AST_WIRE
))
453 const_fold_here
= true, in_param_here
= true;
454 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
)
455 const_fold_here
= true;
456 if (i
== 0 && (type
== AST_ASSIGN
|| type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
))
457 in_lvalue_here
= true;
458 if (type
== AST_BLOCK
) {
459 current_block
= this;
460 current_block_child
= children
[i
];
462 if ((type
== AST_ALWAYS
|| type
== AST_INITIAL
) && children
[i
]->type
== AST_BLOCK
)
463 current_top_block
= children
[i
];
464 if (i
== 0 && child_0_is_self_determined
)
465 width_hint_here
= -1, sign_hint_here
= false;
466 if (i
== 1 && child_1_is_self_determined
)
467 width_hint_here
= -1, sign_hint_here
= false;
468 if (i
== 2 && child_2_is_self_determined
)
469 width_hint_here
= -1, sign_hint_here
= false;
470 if (children_are_self_determined
)
471 width_hint_here
= -1, sign_hint_here
= false;
472 did_something_here
= children
[i
]->simplify(const_fold_here
, at_zero
, in_lvalue_here
, stage
, width_hint_here
, sign_hint_here
, in_param_here
);
473 if (did_something_here
)
474 did_something
= true;
476 if (stage
== 2 && children
[i
]->type
== AST_INITIAL
&& current_ast_mod
!= this) {
477 current_ast_mod
->children
.push_back(children
[i
]);
478 children
.erase(children
.begin() + (i
--));
479 did_something
= true;
482 for (auto &attr
: attributes
) {
483 while (attr
.second
->simplify(true, false, false, stage
, -1, false, true))
484 did_something
= true;
487 if (reset_width_after_children
) {
488 width_hint
= backup_width_hint
;
489 sign_hint
= backup_sign_hint
;
491 detectSignWidth(width_hint
, sign_hint
);
494 current_block
= backup_current_block
;
495 current_block_child
= backup_current_block_child
;
496 current_top_block
= backup_current_top_block
;
498 for (auto it
= backup_scope
.begin(); it
!= backup_scope
.end(); it
++) {
499 if (it
->second
== NULL
)
500 current_scope
.erase(it
->first
);
502 current_scope
[it
->first
] = it
->second
;
505 current_filename
= filename
;
506 set_line_num(linenum
);
508 if (type
== AST_MODULE
)
509 current_scope
.clear();
511 // convert defparam nodes to cell parameters
512 if (type
== AST_DEFPARAM
&& !str
.empty()) {
513 size_t pos
= str
.rfind('.');
514 if (pos
== std::string::npos
)
515 log_error("Defparam `%s' does not contain a dot (module/parameter separator) at %s:%d!\n",
516 RTLIL::unescape_id(str
).c_str(), filename
.c_str(), linenum
);
517 std::string modname
= str
.substr(0, pos
), paraname
= "\\" + str
.substr(pos
+1);
518 if (current_scope
.count(modname
) == 0 || current_scope
.at(modname
)->type
!= AST_CELL
)
519 log_error("Can't find cell for defparam `%s . %s` at %s:%d!\n", RTLIL::unescape_id(modname
).c_str(), RTLIL::unescape_id(paraname
).c_str(), filename
.c_str(), linenum
);
520 AstNode
*cell
= current_scope
.at(modname
), *paraset
= clone();
521 cell
->children
.insert(cell
->children
.begin() + 1, paraset
);
522 paraset
->type
= AST_PARASET
;
523 paraset
->str
= paraname
;
527 // resolve constant prefixes
528 if (type
== AST_PREFIX
) {
529 if (children
[0]->type
!= AST_CONSTANT
) {
530 // dumpAst(NULL, "> ");
531 log_error("Index in generate block prefix syntax at %s:%d is not constant!\n", filename
.c_str(), linenum
);
533 log_assert(children
[1]->type
== AST_IDENTIFIER
);
534 newNode
= children
[1]->clone();
535 const char *second_part
= children
[1]->str
.c_str();
536 if (second_part
[0] == '\\')
538 newNode
->str
= stringf("%s[%d].%s", str
.c_str(), children
[0]->integer
, second_part
);
542 // evaluate TO_BITS nodes
543 if (type
== AST_TO_BITS
) {
544 if (children
[0]->type
!= AST_CONSTANT
)
545 log_error("Left operand of to_bits expression is not constant at %s:%d!\n", filename
.c_str(), linenum
);
546 if (children
[1]->type
!= AST_CONSTANT
)
547 log_error("Right operand of to_bits expression is not constant at %s:%d!\n", filename
.c_str(), linenum
);
548 RTLIL::Const new_value
= children
[1]->bitsAsConst(children
[0]->bitsAsConst().as_int(), children
[1]->is_signed
);
549 newNode
= mkconst_bits(new_value
.bits
, children
[1]->is_signed
);
553 // annotate constant ranges
554 if (type
== AST_RANGE
) {
555 bool old_range_valid
= range_valid
;
557 range_swapped
= false;
560 log_assert(children
.size() >= 1);
561 if (children
[0]->type
== AST_CONSTANT
) {
563 range_left
= children
[0]->integer
;
564 if (children
.size() == 1)
565 range_right
= range_left
;
567 if (children
.size() >= 2) {
568 if (children
[1]->type
== AST_CONSTANT
)
569 range_right
= children
[1]->integer
;
573 if (old_range_valid
!= range_valid
)
574 did_something
= true;
575 if (range_valid
&& range_left
>= 0 && range_right
> range_left
) {
576 int tmp
= range_right
;
577 range_right
= range_left
;
579 range_swapped
= true;
583 // annotate wires with their ranges
584 if (type
== AST_WIRE
) {
585 if (children
.size() > 0) {
586 if (children
[0]->range_valid
) {
588 did_something
= true;
590 range_swapped
= children
[0]->range_swapped
;
591 range_left
= children
[0]->range_left
;
592 range_right
= children
[0]->range_right
;
596 did_something
= true;
598 range_swapped
= false;
604 // resolve multiranges on memory decl
605 if (type
== AST_MEMORY
&& children
.size() > 1 && children
[1]->type
== AST_MULTIRANGE
)
608 multirange_dimensions
.clear();
609 for (auto range
: children
[1]->children
) {
610 if (!range
->range_valid
)
611 log_error("Non-constant range on memory decl at %s:%d.\n", filename
.c_str(), linenum
);
612 multirange_dimensions
.push_back(std::min(range
->range_left
, range
->range_right
));
613 multirange_dimensions
.push_back(std::max(range
->range_left
, range
->range_right
) - std::min(range
->range_left
, range
->range_right
) + 1);
614 total_size
*= multirange_dimensions
.back();
617 children
[1] = new AstNode(AST_RANGE
, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size
-1, true));
618 did_something
= true;
621 // resolve multiranges on memory access
622 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
&& children
.size() > 0 && children
[0]->type
== AST_MULTIRANGE
)
624 AstNode
*index_expr
= nullptr;
626 for (int i
= 0; 2*i
< GetSize(id2ast
->multirange_dimensions
); i
++)
628 if (GetSize(children
[0]->children
) < i
)
629 log_error("Insufficient number of array indices for %s at %s:%d.\n", log_id(str
), filename
.c_str(), linenum
);
631 AstNode
*new_index_expr
= children
[0]->children
[i
]->children
.at(0)->clone();
633 if (id2ast
->multirange_dimensions
[2*i
])
634 new_index_expr
= new AstNode(AST_SUB
, new_index_expr
, AstNode::mkconst_int(id2ast
->multirange_dimensions
[2*i
], true));
637 index_expr
= new_index_expr
;
639 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
);
642 for (int i
= GetSize(id2ast
->multirange_dimensions
)/1; i
< GetSize(children
[0]->children
); i
++)
643 children
.push_back(children
[0]->children
[i
]->clone());
646 if (index_expr
== nullptr)
647 children
.erase(children
.begin());
649 children
[0] = new AstNode(AST_RANGE
, index_expr
);
651 did_something
= true;
654 // trim/extend parameters
655 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
) {
656 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
657 if (!children
[1]->range_valid
)
658 log_error("Non-constant width range on parameter decl at %s:%d.\n", filename
.c_str(), linenum
);
659 int width
= children
[1]->range_left
- children
[1]->range_right
+ 1;
660 if (children
[0]->type
== AST_REALVALUE
) {
661 RTLIL::Const constvalue
= children
[0]->realAsConst(width
);
662 log_warning("converting real value %e to binary %s at %s:%d.\n",
663 children
[0]->realvalue
, log_signal(constvalue
), filename
.c_str(), linenum
);
665 children
[0] = mkconst_bits(constvalue
.bits
, sign_hint
);
666 did_something
= true;
668 if (children
[0]->type
== AST_CONSTANT
) {
669 if (width
!= int(children
[0]->bits
.size())) {
670 RTLIL::SigSpec
sig(children
[0]->bits
);
671 sig
.extend_u0(width
, children
[0]->is_signed
);
672 AstNode
*old_child_0
= children
[0];
673 children
[0] = mkconst_bits(sig
.as_const().bits
, children
[0]->is_signed
);
676 children
[0]->is_signed
= is_signed
;
679 range_swapped
= children
[1]->range_swapped
;
680 range_left
= children
[1]->range_left
;
681 range_right
= children
[1]->range_right
;
683 if (children
.size() > 1 && children
[1]->type
== AST_REALVALUE
&& children
[0]->type
== AST_CONSTANT
) {
684 double as_realvalue
= children
[0]->asReal(sign_hint
);
686 children
[0] = new AstNode(AST_REALVALUE
);
687 children
[0]->realvalue
= as_realvalue
;
688 did_something
= true;
692 // annotate identifiers using scope resolution and create auto-wires as needed
693 if (type
== AST_IDENTIFIER
) {
694 if (current_scope
.count(str
) == 0) {
695 for (auto node
: current_ast_mod
->children
) {
696 if ((node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
697 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
) && str
== node
->str
) {
698 current_scope
[node
->str
] = node
;
703 if (current_scope
.count(str
) == 0) {
704 // log_warning("Creating auto-wire `%s' in module `%s'.\n", str.c_str(), current_ast_mod->str.c_str());
705 AstNode
*auto_wire
= new AstNode(AST_AUTOWIRE
);
706 auto_wire
->str
= str
;
707 current_ast_mod
->children
.push_back(auto_wire
);
708 current_scope
[str
] = auto_wire
;
709 did_something
= true;
711 if (id2ast
!= current_scope
[str
]) {
712 id2ast
= current_scope
[str
];
713 did_something
= true;
717 // split memory access with bit select to individual statements
718 if (type
== AST_IDENTIFIER
&& children
.size() == 2 && children
[0]->type
== AST_RANGE
&& children
[1]->type
== AST_RANGE
&& !in_lvalue
)
720 if (id2ast
== NULL
|| id2ast
->type
!= AST_MEMORY
|| children
[0]->children
.size() != 1)
721 log_error("Invalid bit-select on memory access at %s:%d!\n", filename
.c_str(), linenum
);
723 int mem_width
, mem_size
, addr_bits
;
724 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
726 std::stringstream sstr
;
727 sstr
<< "$mem2bits$" << children
[0]->str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
728 std::string wire_id
= sstr
.str();
730 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
733 wire
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
734 current_ast_mod
->children
.push_back(wire
);
735 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
737 AstNode
*data
= clone();
738 delete data
->children
[1];
739 data
->children
.pop_back();
741 AstNode
*assign
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), data
);
742 assign
->children
[0]->str
= wire_id
;
746 size_t assign_idx
= 0;
747 while (assign_idx
< current_block
->children
.size() && current_block
->children
[assign_idx
] != current_block_child
)
749 log_assert(assign_idx
< current_block
->children
.size());
750 current_block
->children
.insert(current_block
->children
.begin()+assign_idx
, assign
);
755 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
756 proc
->children
[0]->children
.push_back(assign
);
757 current_ast_mod
->children
.push_back(proc
);
760 newNode
= new AstNode(AST_IDENTIFIER
, children
[1]->clone());
761 newNode
->str
= wire_id
;
762 newNode
->id2ast
= wire
;
766 if (type
== AST_WHILE
)
767 log_error("While loops are only allowed in constant functions at %s:%d!\n", filename
.c_str(), linenum
);
769 if (type
== AST_REPEAT
)
770 log_error("Repeat loops are only allowed in constant functions at %s:%d!\n", filename
.c_str(), linenum
);
772 // unroll for loops and generate-for blocks
773 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && children
.size() != 0)
775 AstNode
*init_ast
= children
[0];
776 AstNode
*while_ast
= children
[1];
777 AstNode
*next_ast
= children
[2];
778 AstNode
*body_ast
= children
[3];
780 while (body_ast
->type
== AST_GENBLOCK
&& body_ast
->str
.empty() &&
781 body_ast
->children
.size() == 1 && body_ast
->children
.at(0)->type
== AST_GENBLOCK
)
782 body_ast
= body_ast
->children
.at(0);
784 if (init_ast
->type
!= AST_ASSIGN_EQ
)
785 log_error("Unsupported 1st expression of generate for-loop at %s:%d!\n", filename
.c_str(), linenum
);
786 if (next_ast
->type
!= AST_ASSIGN_EQ
)
787 log_error("Unsupported 3rd expression of generate for-loop at %s:%d!\n", filename
.c_str(), linenum
);
789 if (type
== AST_GENFOR
) {
790 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
791 log_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a gen var!\n", filename
.c_str(), linenum
);
792 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
793 log_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a gen var!\n", filename
.c_str(), linenum
);
795 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
796 log_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a register!\n", filename
.c_str(), linenum
);
797 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
798 log_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a register!\n", filename
.c_str(), linenum
);
801 if (init_ast
->children
[0]->id2ast
!= next_ast
->children
[0]->id2ast
)
802 log_error("Incompatible left-hand sides in 1st and 3rd expression of generate for-loop at %s:%d!\n", filename
.c_str(), linenum
);
804 // eval 1st expression
805 AstNode
*varbuf
= init_ast
->children
[1]->clone();
806 while (varbuf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
808 if (varbuf
->type
!= AST_CONSTANT
)
809 log_error("Right hand side of 1st expression of generate for-loop at %s:%d is not constant!\n", filename
.c_str(), linenum
);
811 varbuf
= new AstNode(AST_LOCALPARAM
, varbuf
);
812 varbuf
->str
= init_ast
->children
[0]->str
;
814 AstNode
*backup_scope_varbuf
= current_scope
[varbuf
->str
];
815 current_scope
[varbuf
->str
] = varbuf
;
817 size_t current_block_idx
= 0;
818 if (type
== AST_FOR
) {
819 while (current_block_idx
< current_block
->children
.size() &&
820 current_block
->children
[current_block_idx
] != current_block_child
)
826 // eval 2nd expression
827 AstNode
*buf
= while_ast
->clone();
828 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
830 if (buf
->type
!= AST_CONSTANT
)
831 log_error("2nd expression of generate for-loop at %s:%d is not constant!\n", filename
.c_str(), linenum
);
833 if (buf
->integer
== 0) {
840 int index
= varbuf
->children
[0]->integer
;
841 if (body_ast
->type
== AST_GENBLOCK
)
842 buf
= body_ast
->clone();
844 buf
= new AstNode(AST_GENBLOCK
, body_ast
->clone());
845 if (buf
->str
.empty()) {
846 std::stringstream sstr
;
847 sstr
<< "$genblock$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
848 buf
->str
= sstr
.str();
850 std::map
<std::string
, std::string
> name_map
;
851 std::stringstream sstr
;
852 sstr
<< buf
->str
<< "[" << index
<< "].";
853 buf
->expand_genblock(varbuf
->str
, sstr
.str(), name_map
);
855 if (type
== AST_GENFOR
) {
856 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
857 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
858 current_ast_mod
->children
.push_back(buf
->children
[i
]);
861 for (size_t i
= 0; i
< buf
->children
.size(); i
++)
862 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
->children
[i
]);
864 buf
->children
.clear();
867 // eval 3rd expression
868 buf
= next_ast
->children
[1]->clone();
869 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
871 if (buf
->type
!= AST_CONSTANT
)
872 log_error("Right hand side of 3rd expression of generate for-loop at %s:%d is not constant!\n", filename
.c_str(), linenum
);
874 delete varbuf
->children
[0];
875 varbuf
->children
[0] = buf
;
878 current_scope
[varbuf
->str
] = backup_scope_varbuf
;
881 did_something
= true;
884 // transform block with name
885 if (type
== AST_BLOCK
&& !str
.empty())
887 std::map
<std::string
, std::string
> name_map
;
888 expand_genblock(std::string(), str
+ ".", name_map
);
890 std::vector
<AstNode
*> new_children
;
891 for (size_t i
= 0; i
< children
.size(); i
++)
892 if (children
[i
]->type
== AST_WIRE
) {
893 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
894 current_ast_mod
->children
.push_back(children
[i
]);
895 current_scope
[children
[i
]->str
] = children
[i
];
897 new_children
.push_back(children
[i
]);
899 children
.swap(new_children
);
900 did_something
= true;
904 // simplify unconditional generate block
905 if (type
== AST_GENBLOCK
&& children
.size() != 0)
908 std::map
<std::string
, std::string
> name_map
;
909 expand_genblock(std::string(), str
+ ".", name_map
);
912 for (size_t i
= 0; i
< children
.size(); i
++) {
913 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
914 current_ast_mod
->children
.push_back(children
[i
]);
918 did_something
= true;
921 // simplify generate-if blocks
922 if (type
== AST_GENIF
&& children
.size() != 0)
924 AstNode
*buf
= children
[0]->clone();
925 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
926 if (buf
->type
!= AST_CONSTANT
) {
927 // for (auto f : log_files)
928 // dumpAst(f, "verilog-ast> ");
929 log_error("Condition for generate if at %s:%d is not constant!\n", filename
.c_str(), linenum
);
931 if (buf
->asBool() != 0) {
933 buf
= children
[1]->clone();
936 buf
= children
.size() > 2 ? children
[2]->clone() : NULL
;
941 if (buf
->type
!= AST_GENBLOCK
)
942 buf
= new AstNode(AST_GENBLOCK
, buf
);
944 if (!buf
->str
.empty()) {
945 std::map
<std::string
, std::string
> name_map
;
946 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
949 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
950 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
951 current_ast_mod
->children
.push_back(buf
->children
[i
]);
954 buf
->children
.clear();
959 did_something
= true;
962 // simplify generate-case blocks
963 if (type
== AST_GENCASE
&& children
.size() != 0)
965 AstNode
*buf
= children
[0]->clone();
966 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
967 if (buf
->type
!= AST_CONSTANT
) {
968 // for (auto f : log_files)
969 // dumpAst(f, "verilog-ast> ");
970 log_error("Condition for generate case at %s:%d is not constant!\n", filename
.c_str(), linenum
);
973 bool ref_signed
= buf
->is_signed
;
974 RTLIL::Const ref_value
= buf
->bitsAsConst();
977 AstNode
*selected_case
= NULL
;
978 for (size_t i
= 1; i
< children
.size(); i
++)
980 log_assert(children
.at(i
)->type
== AST_COND
);
982 AstNode
*this_genblock
= NULL
;
983 for (auto child
: children
.at(i
)->children
) {
984 log_assert(this_genblock
== NULL
);
985 if (child
->type
== AST_GENBLOCK
)
986 this_genblock
= child
;
989 for (auto child
: children
.at(i
)->children
)
991 if (child
->type
== AST_DEFAULT
) {
992 if (selected_case
== NULL
)
993 selected_case
= this_genblock
;
996 if (child
->type
== AST_GENBLOCK
)
999 buf
= child
->clone();
1000 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1001 if (buf
->type
!= AST_CONSTANT
) {
1002 // for (auto f : log_files)
1003 // dumpAst(f, "verilog-ast> ");
1004 log_error("Expression in generate case at %s:%d is not constant!\n", filename
.c_str(), linenum
);
1007 bool is_selected
= RTLIL::const_eq(ref_value
, buf
->bitsAsConst(), ref_signed
&& buf
->is_signed
, ref_signed
&& buf
->is_signed
, 1).as_bool();
1011 selected_case
= this_genblock
;
1012 i
= children
.size();
1018 if (selected_case
!= NULL
)
1020 log_assert(selected_case
->type
== AST_GENBLOCK
);
1021 buf
= selected_case
->clone();
1023 if (!buf
->str
.empty()) {
1024 std::map
<std::string
, std::string
> name_map
;
1025 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1028 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1029 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1030 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1033 buf
->children
.clear();
1038 did_something
= true;
1041 // unroll cell arrays
1042 if (type
== AST_CELLARRAY
)
1044 if (!children
.at(0)->range_valid
)
1045 log_error("Non-constant array range on cell array at %s:%d.\n", filename
.c_str(), linenum
);
1047 newNode
= new AstNode(AST_GENBLOCK
);
1048 int num
= std::max(children
.at(0)->range_left
, children
.at(0)->range_right
) - std::min(children
.at(0)->range_left
, children
.at(0)->range_right
) + 1;
1050 for (int i
= 0; i
< num
; i
++) {
1051 int idx
= children
.at(0)->range_left
> children
.at(0)->range_right
? children
.at(0)->range_right
+ i
: children
.at(0)->range_right
- i
;
1052 AstNode
*new_cell
= children
.at(1)->clone();
1053 newNode
->children
.push_back(new_cell
);
1054 new_cell
->str
+= stringf("[%d]", idx
);
1055 if (new_cell
->type
== AST_PRIMITIVE
) {
1056 log_error("Cell arrays of primitives are currently not supported at %s:%d.\n", filename
.c_str(), linenum
);
1058 log_assert(new_cell
->children
.at(0)->type
== AST_CELLTYPE
);
1059 new_cell
->children
.at(0)->str
= stringf("$array:%d:%d:%s", i
, num
, new_cell
->children
.at(0)->str
.c_str());
1066 // replace primitives with assignmens
1067 if (type
== AST_PRIMITIVE
)
1069 if (children
.size() < 2)
1070 log_error("Insufficient number of arguments for primitive `%s' at %s:%d!\n",
1071 str
.c_str(), filename
.c_str(), linenum
);
1073 std::vector
<AstNode
*> children_list
;
1074 for (auto child
: children
) {
1075 log_assert(child
->type
== AST_ARGUMENT
);
1076 log_assert(child
->children
.size() == 1);
1077 children_list
.push_back(child
->children
[0]);
1078 child
->children
.clear();
1083 if (str
== "bufif0" || str
== "bufif1" || str
== "notif0" || str
== "notif1")
1085 if (children_list
.size() != 3)
1086 log_error("Invalid number of arguments for primitive `%s' at %s:%d!\n",
1087 str
.c_str(), filename
.c_str(), linenum
);
1089 std::vector
<RTLIL::State
> z_const(1, RTLIL::State::Sz
);
1091 AstNode
*mux_input
= children_list
.at(1);
1092 if (str
== "notif0" || str
== "notif1") {
1093 mux_input
= new AstNode(AST_BIT_NOT
, mux_input
);
1095 AstNode
*node
= new AstNode(AST_TERNARY
, children_list
.at(2));
1096 if (str
== "bufif0") {
1097 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1098 node
->children
.push_back(mux_input
);
1100 node
->children
.push_back(mux_input
);
1101 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1106 children
.push_back(children_list
.at(0));
1107 children
.push_back(node
);
1108 did_something
= true;
1112 AstNodeType op_type
= AST_NONE
;
1113 bool invert_results
= false;
1116 op_type
= AST_BIT_AND
;
1118 op_type
= AST_BIT_AND
, invert_results
= true;
1120 op_type
= AST_BIT_OR
;
1122 op_type
= AST_BIT_OR
, invert_results
= true;
1124 op_type
= AST_BIT_XOR
;
1126 op_type
= AST_BIT_XOR
, invert_results
= true;
1130 op_type
= AST_POS
, invert_results
= true;
1131 log_assert(op_type
!= AST_NONE
);
1133 AstNode
*node
= children_list
[1];
1134 if (op_type
!= AST_POS
)
1135 for (size_t i
= 2; i
< children_list
.size(); i
++)
1136 node
= new AstNode(op_type
, node
, children_list
[i
]);
1138 node
= new AstNode(AST_BIT_NOT
, node
);
1142 children
.push_back(children_list
[0]);
1143 children
.push_back(node
);
1144 did_something
= true;
1148 // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
1149 // a big case block that selects the correct single-bit assignment.
1150 if (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) {
1151 if (children
[0]->type
!= AST_IDENTIFIER
|| children
[0]->children
.size() == 0)
1152 goto skip_dynamic_range_lvalue_expansion
;
1153 if (children
[0]->children
[0]->range_valid
|| did_something
)
1154 goto skip_dynamic_range_lvalue_expansion
;
1155 if (children
[0]->id2ast
== NULL
|| children
[0]->id2ast
->type
!= AST_WIRE
)
1156 goto skip_dynamic_range_lvalue_expansion
;
1157 if (!children
[0]->id2ast
->range_valid
)
1158 goto skip_dynamic_range_lvalue_expansion
;
1159 int source_width
= children
[0]->id2ast
->range_left
- children
[0]->id2ast
->range_right
+ 1;
1160 int result_width
= 1;
1161 AstNode
*shift_expr
= NULL
;
1162 AstNode
*range
= children
[0]->children
[0];
1163 if (range
->children
.size() == 1) {
1164 shift_expr
= range
->children
[0]->clone();
1166 shift_expr
= range
->children
[1]->clone();
1167 AstNode
*left_at_zero_ast
= range
->children
[0]->clone();
1168 AstNode
*right_at_zero_ast
= range
->children
[1]->clone();
1169 while (left_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1170 while (right_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1171 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
1172 log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
1173 str
.c_str(), filename
.c_str(), linenum
);
1174 result_width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
1176 did_something
= true;
1177 newNode
= new AstNode(AST_CASE
, shift_expr
);
1178 for (int i
= 0; i
<= source_width
-result_width
; i
++) {
1179 int start_bit
= children
[0]->id2ast
->range_right
+ i
;
1180 AstNode
*cond
= new AstNode(AST_COND
, mkconst_int(start_bit
, true));
1181 AstNode
*lvalue
= children
[0]->clone();
1182 lvalue
->delete_children();
1183 lvalue
->children
.push_back(new AstNode(AST_RANGE
,
1184 mkconst_int(start_bit
+result_width
-1, true), mkconst_int(start_bit
, true)));
1185 cond
->children
.push_back(new AstNode(AST_BLOCK
, new AstNode(type
, lvalue
, children
[1]->clone())));
1186 newNode
->children
.push_back(cond
);
1190 skip_dynamic_range_lvalue_expansion
:;
1192 if (stage
> 1 && type
== AST_ASSERT
&& current_block
!= NULL
)
1194 std::stringstream sstr
;
1195 sstr
<< "$assert$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1196 std::string id_check
= sstr
.str() + "_CHECK", id_en
= sstr
.str() + "_EN";
1198 AstNode
*wire_check
= new AstNode(AST_WIRE
);
1199 wire_check
->str
= id_check
;
1200 current_ast_mod
->children
.push_back(wire_check
);
1201 current_scope
[wire_check
->str
] = wire_check
;
1202 while (wire_check
->simplify(true, false, false, 1, -1, false, false)) { }
1204 AstNode
*wire_en
= new AstNode(AST_WIRE
);
1205 wire_en
->str
= id_en
;
1206 current_ast_mod
->children
.push_back(wire_en
);
1207 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)))));
1208 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->str
= id_en
;
1209 current_scope
[wire_en
->str
] = wire_en
;
1210 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
1212 std::vector
<RTLIL::State
> x_bit
;
1213 x_bit
.push_back(RTLIL::State::Sx
);
1215 AstNode
*assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bit
, false));
1216 assign_check
->children
[0]->str
= id_check
;
1218 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, 1));
1219 assign_en
->children
[0]->str
= id_en
;
1221 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
1222 default_signals
->children
.push_back(assign_check
);
1223 default_signals
->children
.push_back(assign_en
);
1224 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
1226 assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_REDUCE_BOOL
, children
[0]->clone()));
1227 assign_check
->children
[0]->str
= id_check
;
1229 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(1, false, 1));
1230 assign_en
->children
[0]->str
= id_en
;
1232 newNode
= new AstNode(AST_BLOCK
);
1233 newNode
->children
.push_back(assign_check
);
1234 newNode
->children
.push_back(assign_en
);
1236 AstNode
*assertnode
= new AstNode(AST_ASSERT
);
1237 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1238 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1239 assertnode
->children
[0]->str
= id_check
;
1240 assertnode
->children
[1]->str
= id_en
;
1241 assertnode
->attributes
.swap(attributes
);
1242 current_ast_mod
->children
.push_back(assertnode
);
1247 if (stage
> 1 && type
== AST_ASSERT
&& children
.size() == 1)
1249 children
[0] = new AstNode(AST_REDUCE_BOOL
, children
[0]->clone());
1250 children
.push_back(mkconst_int(1, false, 1));
1251 did_something
= true;
1254 // found right-hand side identifier for memory -> replace with memory read port
1255 if (stage
> 1 && type
== AST_IDENTIFIER
&& id2ast
!= NULL
&& id2ast
->type
== AST_MEMORY
&& !in_lvalue
&&
1256 children
[0]->type
== AST_RANGE
&& children
[0]->children
.size() == 1) {
1257 newNode
= new AstNode(AST_MEMRD
, children
[0]->children
[0]->clone());
1259 newNode
->id2ast
= id2ast
;
1263 // assignment with memory in left-hand side expression -> replace with memory write port
1264 if (stage
> 1 && (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_IDENTIFIER
&&
1265 children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
&& children
[0]->id2ast
->children
.size() >= 2 &&
1266 children
[0]->id2ast
->children
[0]->range_valid
&& children
[0]->id2ast
->children
[1]->range_valid
&&
1267 (children
[0]->children
.size() == 1 || children
[0]->children
.size() == 2) && children
[0]->children
[0]->type
== AST_RANGE
)
1269 std::stringstream sstr
;
1270 sstr
<< "$memwr$" << children
[0]->str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1271 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA", id_en
= sstr
.str() + "_EN";
1273 if (type
== AST_ASSIGN_EQ
) {
1274 pair
<string
, int> this_blocking_assignment_warn(filename
, linenum
);
1275 if (this_blocking_assignment_warn
!= last_blocking_assignment_warn
)
1276 log_warning("Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n",
1277 filename
.c_str(), linenum
);
1278 last_blocking_assignment_warn
= this_blocking_assignment_warn
;
1281 int mem_width
, mem_size
, addr_bits
;
1282 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
1284 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
1285 wire_addr
->str
= id_addr
;
1286 current_ast_mod
->children
.push_back(wire_addr
);
1287 current_scope
[wire_addr
->str
] = wire_addr
;
1288 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
1290 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
1291 wire_data
->str
= id_data
;
1292 current_ast_mod
->children
.push_back(wire_data
);
1293 current_scope
[wire_data
->str
] = wire_data
;
1294 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
1296 AstNode
*wire_en
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
1297 wire_en
->str
= id_en
;
1298 current_ast_mod
->children
.push_back(wire_en
);
1299 current_scope
[wire_en
->str
] = wire_en
;
1300 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
1302 std::vector
<RTLIL::State
> x_bits_addr
, x_bits_data
, set_bits_en
;
1303 for (int i
= 0; i
< addr_bits
; i
++)
1304 x_bits_addr
.push_back(RTLIL::State::Sx
);
1305 for (int i
= 0; i
< mem_width
; i
++)
1306 x_bits_data
.push_back(RTLIL::State::Sx
);
1307 for (int i
= 0; i
< mem_width
; i
++)
1308 set_bits_en
.push_back(RTLIL::State::S1
);
1310 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_addr
, false));
1311 assign_addr
->children
[0]->str
= id_addr
;
1313 AstNode
*assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_data
, false));
1314 assign_data
->children
[0]->str
= id_data
;
1316 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, mem_width
));
1317 assign_en
->children
[0]->str
= id_en
;
1319 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
1320 default_signals
->children
.push_back(assign_addr
);
1321 default_signals
->children
.push_back(assign_data
);
1322 default_signals
->children
.push_back(assign_en
);
1323 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
1325 assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
1326 assign_addr
->children
[0]->str
= id_addr
;
1328 if (children
[0]->children
.size() == 2)
1330 if (children
[0]->children
[1]->range_valid
)
1332 int offset
= children
[0]->children
[1]->range_right
;
1333 int width
= children
[0]->children
[1]->range_left
- offset
+ 1;
1335 std::vector
<RTLIL::State
> padding_x(offset
, RTLIL::State::Sx
);
1337 for (int i
= 0; i
< mem_width
; i
++)
1338 set_bits_en
[i
] = offset
<= i
&& i
< offset
+width
? RTLIL::State::S1
: RTLIL::State::S0
;
1340 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1341 new AstNode(AST_CONCAT
, mkconst_bits(padding_x
, false), children
[1]->clone()));
1342 assign_data
->children
[0]->str
= id_data
;
1344 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
1345 assign_en
->children
[0]->str
= id_en
;
1349 AstNode
*the_range
= children
[0]->children
[1];
1350 AstNode
*left_at_zero_ast
= the_range
->children
[0]->clone();
1351 AstNode
*right_at_zero_ast
= the_range
->children
.size() >= 2 ? the_range
->children
[1]->clone() : left_at_zero_ast
->clone();
1352 AstNode
*offset_ast
= right_at_zero_ast
->clone();
1354 while (left_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
1355 while (right_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
1356 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
1357 log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n", str
.c_str(), filename
.c_str(), linenum
);
1358 int width
= left_at_zero_ast
->integer
- right_at_zero_ast
->integer
+ 1;
1360 for (int i
= 0; i
< mem_width
; i
++)
1361 set_bits_en
[i
] = i
< width
? RTLIL::State::S1
: RTLIL::State::S0
;
1363 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1364 new AstNode(AST_SHIFT_LEFT
, children
[1]->clone(), offset_ast
->clone()));
1365 assign_data
->children
[0]->str
= id_data
;
1367 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1368 new AstNode(AST_SHIFT_LEFT
, mkconst_bits(set_bits_en
, false), offset_ast
->clone()));
1369 assign_en
->children
[0]->str
= id_en
;
1371 delete left_at_zero_ast
;
1372 delete right_at_zero_ast
;
1378 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[1]->clone());
1379 assign_data
->children
[0]->str
= id_data
;
1381 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
1382 assign_en
->children
[0]->str
= id_en
;
1385 newNode
= new AstNode(AST_BLOCK
);
1386 newNode
->children
.push_back(assign_addr
);
1387 newNode
->children
.push_back(assign_data
);
1388 newNode
->children
.push_back(assign_en
);
1390 AstNode
*wrnode
= new AstNode(AST_MEMWR
);
1391 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1392 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1393 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1394 wrnode
->str
= children
[0]->str
;
1395 wrnode
->children
[0]->str
= id_addr
;
1396 wrnode
->children
[1]->str
= id_data
;
1397 wrnode
->children
[2]->str
= id_en
;
1398 current_ast_mod
->children
.push_back(wrnode
);
1403 // replace function and task calls with the code from the function or task
1404 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && !str
.empty())
1406 if (type
== AST_FCALL
)
1408 if (str
== "\\$clog2")
1410 if (children
.size() != 1)
1411 log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
1412 RTLIL::unescape_id(str
).c_str(), int(children
.size()), filename
.c_str(), linenum
);
1414 AstNode
*buf
= children
[0]->clone();
1415 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1416 if (buf
->type
!= AST_CONSTANT
)
1417 log_error("Failed to evaluate system function `%s' with non-constant value at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
1419 RTLIL::Const arg_value
= buf
->bitsAsConst();
1420 if (arg_value
.as_bool())
1421 arg_value
= const_sub(arg_value
, 1, false, false, GetSize(arg_value
));
1424 uint32_t result
= 0;
1425 for (size_t i
= 0; i
< arg_value
.bits
.size(); i
++)
1426 if (arg_value
.bits
.at(i
) == RTLIL::State::S1
)
1429 newNode
= mkconst_int(result
, false);
1433 if (str
== "\\$ln" || str
== "\\$log10" || str
== "\\$exp" || str
== "\\$sqrt" || str
== "\\$pow" ||
1434 str
== "\\$floor" || str
== "\\$ceil" || str
== "\\$sin" || str
== "\\$cos" || str
== "\\$tan" ||
1435 str
== "\\$asin" || str
== "\\$acos" || str
== "\\$atan" || str
== "\\$atan2" || str
== "\\$hypot" ||
1436 str
== "\\$sinh" || str
== "\\$cosh" || str
== "\\$tanh" || str
== "\\$asinh" || str
== "\\$acosh" || str
== "\\$atanh")
1438 bool func_with_two_arguments
= str
== "\\$pow" || str
== "\\$atan2" || str
== "\\$hypot";
1439 double x
= 0, y
= 0;
1441 if (func_with_two_arguments
) {
1442 if (children
.size() != 2)
1443 log_error("System function %s got %d arguments, expected 2 at %s:%d.\n",
1444 RTLIL::unescape_id(str
).c_str(), int(children
.size()), filename
.c_str(), linenum
);
1446 if (children
.size() != 1)
1447 log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
1448 RTLIL::unescape_id(str
).c_str(), int(children
.size()), filename
.c_str(), linenum
);
1451 if (children
.size() >= 1) {
1452 while (children
[0]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1453 if (!children
[0]->isConst())
1454 log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
1455 RTLIL::unescape_id(str
).c_str(), filename
.c_str(), linenum
);
1456 int child_width_hint
= width_hint
;
1457 bool child_sign_hint
= sign_hint
;
1458 children
[0]->detectSignWidth(child_width_hint
, child_sign_hint
);
1459 x
= children
[0]->asReal(child_sign_hint
);
1462 if (children
.size() >= 2) {
1463 while (children
[1]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1464 if (!children
[1]->isConst())
1465 log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
1466 RTLIL::unescape_id(str
).c_str(), filename
.c_str(), linenum
);
1467 int child_width_hint
= width_hint
;
1468 bool child_sign_hint
= sign_hint
;
1469 children
[1]->detectSignWidth(child_width_hint
, child_sign_hint
);
1470 y
= children
[1]->asReal(child_sign_hint
);
1473 newNode
= new AstNode(AST_REALVALUE
);
1474 if (str
== "\\$ln") newNode
->realvalue
= ::log(x
);
1475 else if (str
== "\\$log10") newNode
->realvalue
= ::log10(x
);
1476 else if (str
== "\\$exp") newNode
->realvalue
= ::exp(x
);
1477 else if (str
== "\\$sqrt") newNode
->realvalue
= ::sqrt(x
);
1478 else if (str
== "\\$pow") newNode
->realvalue
= ::pow(x
, y
);
1479 else if (str
== "\\$floor") newNode
->realvalue
= ::floor(x
);
1480 else if (str
== "\\$ceil") newNode
->realvalue
= ::ceil(x
);
1481 else if (str
== "\\$sin") newNode
->realvalue
= ::sin(x
);
1482 else if (str
== "\\$cos") newNode
->realvalue
= ::cos(x
);
1483 else if (str
== "\\$tan") newNode
->realvalue
= ::tan(x
);
1484 else if (str
== "\\$asin") newNode
->realvalue
= ::asin(x
);
1485 else if (str
== "\\$acos") newNode
->realvalue
= ::acos(x
);
1486 else if (str
== "\\$atan") newNode
->realvalue
= ::atan(x
);
1487 else if (str
== "\\$atan2") newNode
->realvalue
= ::atan2(x
, y
);
1488 else if (str
== "\\$hypot") newNode
->realvalue
= ::hypot(x
, y
);
1489 else if (str
== "\\$sinh") newNode
->realvalue
= ::sinh(x
);
1490 else if (str
== "\\$cosh") newNode
->realvalue
= ::cosh(x
);
1491 else if (str
== "\\$tanh") newNode
->realvalue
= ::tanh(x
);
1492 else if (str
== "\\$asinh") newNode
->realvalue
= ::asinh(x
);
1493 else if (str
== "\\$acosh") newNode
->realvalue
= ::acosh(x
);
1494 else if (str
== "\\$atanh") newNode
->realvalue
= ::atanh(x
);
1499 if (current_scope
.count(str
) != 0 && current_scope
[str
]->type
== AST_DPI_FUNCTION
)
1501 AstNode
*dpi_decl
= current_scope
[str
];
1503 std::string rtype
, fname
;
1504 std::vector
<std::string
> argtypes
;
1505 std::vector
<AstNode
*> args
;
1507 rtype
= RTLIL::unescape_id(dpi_decl
->children
.at(0)->str
);
1508 fname
= RTLIL::unescape_id(dpi_decl
->children
.at(1)->str
);
1510 for (int i
= 2; i
< GetSize(dpi_decl
->children
); i
++)
1512 if (i
-2 >= GetSize(children
))
1513 log_error("Insufficient number of arguments in DPI function call at %s:%d.\n", filename
.c_str(), linenum
);
1515 argtypes
.push_back(RTLIL::unescape_id(dpi_decl
->children
.at(i
)->str
));
1516 args
.push_back(children
.at(i
-2)->clone());
1517 while (args
.back()->simplify(true, false, false, stage
, -1, false, true)) { }
1519 if (args
.back()->type
!= AST_CONSTANT
&& args
.back()->type
!= AST_REALVALUE
)
1520 log_error("Failed to evaluate DPI function with non-constant argument at %s:%d.\n", filename
.c_str(), linenum
);
1523 newNode
= dpi_call(rtype
, fname
, argtypes
, args
);
1525 for (auto arg
: args
)
1531 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_FUNCTION
)
1532 log_error("Can't resolve function name `%s' at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
1534 if (type
== AST_TCALL
) {
1535 if (str
== "\\$readmemh" || str
== "\\$readmemb")
1537 if (GetSize(children
) < 2 || GetSize(children
) > 4)
1538 log_error("System function %s got %d arguments, expected 2-4 at %s:%d.\n",
1539 RTLIL::unescape_id(str
).c_str(), int(children
.size()), filename
.c_str(), linenum
);
1541 AstNode
*node_filename
= children
[0]->clone();
1542 while (node_filename
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1543 if (node_filename
->type
!= AST_CONSTANT
)
1544 log_error("Failed to evaluate system function `%s' with non-constant 1st argument at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
1546 AstNode
*node_memory
= children
[1]->clone();
1547 while (node_memory
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1548 if (node_memory
->type
!= AST_IDENTIFIER
|| node_memory
->id2ast
== nullptr || node_memory
->id2ast
->type
!= AST_MEMORY
)
1549 log_error("Failed to evaluate system function `%s' with non-memory 2nd argument at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
1551 int start_addr
= -1, finish_addr
= -1;
1553 if (GetSize(children
) > 2) {
1554 AstNode
*node_addr
= children
[2]->clone();
1555 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1556 if (node_addr
->type
!= AST_CONSTANT
)
1557 log_error("Failed to evaluate system function `%s' with non-constant 3rd argument at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
1558 start_addr
= node_addr
->asInt(false);
1561 if (GetSize(children
) > 3) {
1562 AstNode
*node_addr
= children
[3]->clone();
1563 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1564 if (node_addr
->type
!= AST_CONSTANT
)
1565 log_error("Failed to evaluate system function `%s' with non-constant 4th argument at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
1566 finish_addr
= node_addr
->asInt(false);
1569 newNode
= readmem(str
== "\\$readmemh", node_filename
->bitsAsConst().decode_string(), node_memory
->id2ast
, start_addr
, finish_addr
);
1573 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_TASK
)
1574 log_error("Can't resolve task name `%s' at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
1577 AstNode
*decl
= current_scope
[str
];
1579 std::stringstream sstr
;
1580 sstr
<< "$func$" << str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++) << "$";
1581 std::string prefix
= sstr
.str();
1583 bool recommend_const_eval
= false;
1584 bool require_const_eval
= in_param
? false : has_const_only_constructs(recommend_const_eval
);
1585 if ((in_param
|| recommend_const_eval
|| require_const_eval
) && !decl
->attributes
.count("\\via_celltype"))
1587 bool all_args_const
= true;
1588 for (auto child
: children
) {
1589 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
1590 if (child
->type
!= AST_CONSTANT
)
1591 all_args_const
= false;
1594 if (all_args_const
) {
1595 AstNode
*func_workspace
= current_scope
[str
]->clone();
1596 newNode
= func_workspace
->eval_const_function(this);
1597 delete func_workspace
;
1602 log_error("Non-constant function call in constant expression at %s:%d.\n", filename
.c_str(), linenum
);
1603 if (require_const_eval
)
1604 log_error("Function %s can only be called with constant arguments at %s:%d.\n", str
.c_str(), filename
.c_str(), linenum
);
1607 size_t arg_count
= 0;
1608 std::map
<std::string
, std::string
> replace_rules
;
1610 if (current_block
== NULL
)
1612 log_assert(type
== AST_FCALL
);
1614 AstNode
*wire
= NULL
;
1615 for (auto child
: decl
->children
)
1616 if (child
->type
== AST_WIRE
&& child
->str
== str
)
1617 wire
= child
->clone();
1618 log_assert(wire
!= NULL
);
1620 wire
->str
= prefix
+ str
;
1622 wire
->is_input
= false;
1623 wire
->is_output
= false;
1625 current_ast_mod
->children
.push_back(wire
);
1626 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
1628 AstNode
*lvalue
= new AstNode(AST_IDENTIFIER
);
1629 lvalue
->str
= wire
->str
;
1631 AstNode
*always
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
,
1632 new AstNode(AST_ASSIGN_EQ
, lvalue
, clone())));
1633 current_ast_mod
->children
.push_back(always
);
1635 goto replace_fcall_with_id
;
1638 if (decl
->attributes
.count("\\via_celltype"))
1640 std::string celltype
= decl
->attributes
.at("\\via_celltype")->asAttrConst().decode_string();
1641 std::string outport
= str
;
1643 if (celltype
.find(' ') != std::string::npos
) {
1644 int pos
= celltype
.find(' ');
1645 outport
= RTLIL::escape_id(celltype
.substr(pos
+1));
1646 celltype
= RTLIL::escape_id(celltype
.substr(0, pos
));
1648 celltype
= RTLIL::escape_id(celltype
);
1650 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
));
1651 cell
->str
= prefix
.substr(0, GetSize(prefix
)-1);
1652 cell
->children
[0]->str
= celltype
;
1654 for (auto attr
: decl
->attributes
)
1655 if (attr
.first
.str().rfind("\\via_celltype_defparam_", 0) == 0)
1657 AstNode
*cell_arg
= new AstNode(AST_PARASET
, attr
.second
->clone());
1658 cell_arg
->str
= RTLIL::escape_id(attr
.first
.str().substr(strlen("\\via_celltype_defparam_")));
1659 cell
->children
.push_back(cell_arg
);
1662 for (auto child
: decl
->children
)
1663 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
|| (type
== AST_FCALL
&& child
->str
== str
)))
1665 AstNode
*wire
= child
->clone();
1666 wire
->str
= prefix
+ wire
->str
;
1668 wire
->is_input
= false;
1669 wire
->is_output
= false;
1670 current_ast_mod
->children
.push_back(wire
);
1671 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
1673 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
1674 wire_id
->str
= wire
->str
;
1676 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
1678 AstNode
*arg
= children
[arg_count
++]->clone();
1679 AstNode
*assign
= child
->is_input
?
1680 new AstNode(AST_ASSIGN_EQ
, wire_id
->clone(), arg
) :
1681 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
->clone());
1683 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
1684 if (*it
!= current_block_child
)
1686 current_block
->children
.insert(it
, assign
);
1691 AstNode
*cell_arg
= new AstNode(AST_ARGUMENT
, wire_id
);
1692 cell_arg
->str
= child
->str
== str
? outport
: child
->str
;
1693 cell
->children
.push_back(cell_arg
);
1696 current_ast_mod
->children
.push_back(cell
);
1697 goto replace_fcall_with_id
;
1700 for (auto child
: decl
->children
)
1701 if (child
->type
== AST_WIRE
)
1703 AstNode
*wire
= child
->clone();
1704 wire
->str
= prefix
+ wire
->str
;
1706 wire
->is_input
= false;
1707 wire
->is_output
= false;
1708 current_ast_mod
->children
.push_back(wire
);
1709 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
1711 replace_rules
[child
->str
] = wire
->str
;
1713 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
1715 AstNode
*arg
= children
[arg_count
++]->clone();
1716 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
1717 wire_id
->str
= wire
->str
;
1718 AstNode
*assign
= child
->is_input
?
1719 new AstNode(AST_ASSIGN_EQ
, wire_id
, arg
) :
1720 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
);
1722 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
1723 if (*it
!= current_block_child
)
1725 current_block
->children
.insert(it
, assign
);
1731 for (auto child
: decl
->children
)
1732 if (child
->type
!= AST_WIRE
)
1734 AstNode
*stmt
= child
->clone();
1735 stmt
->replace_ids(prefix
, replace_rules
);
1737 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
1738 if (*it
!= current_block_child
)
1740 current_block
->children
.insert(it
, stmt
);
1745 replace_fcall_with_id
:
1746 if (type
== AST_FCALL
) {
1748 type
= AST_IDENTIFIER
;
1751 if (type
== AST_TCALL
)
1753 did_something
= true;
1756 // perform const folding when activated
1760 std::vector
<RTLIL::State
> tmp_bits
;
1761 RTLIL::Const (*const_func
)(const RTLIL::Const
&, const RTLIL::Const
&, bool, bool, int);
1762 RTLIL::Const dummy_arg
;
1766 case AST_IDENTIFIER
:
1767 if (current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
)) {
1768 if (current_scope
[str
]->children
[0]->type
== AST_CONSTANT
) {
1769 if (children
.size() != 0 && children
[0]->type
== AST_RANGE
&& children
[0]->range_valid
) {
1770 std::vector
<RTLIL::State
> data
;
1771 bool param_upto
= current_scope
[str
]->range_valid
&& current_scope
[str
]->range_swapped
;
1772 int param_offset
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_right
: 0;
1773 int param_width
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_left
- current_scope
[str
]->range_right
+ 1 :
1774 GetSize(current_scope
[str
]->children
[0]->bits
);
1775 int tmp_range_left
= children
[0]->range_left
, tmp_range_right
= children
[0]->range_right
;
1777 tmp_range_left
= (param_width
+ 2*param_offset
) - children
[0]->range_right
- 1;
1778 tmp_range_right
= (param_width
+ 2*param_offset
) - children
[0]->range_left
- 1;
1780 for (int i
= tmp_range_right
; i
<= tmp_range_left
; i
++) {
1781 int index
= i
- param_offset
;
1782 if (0 <= index
&& index
< param_width
)
1783 data
.push_back(current_scope
[str
]->children
[0]->bits
[index
]);
1785 data
.push_back(RTLIL::State::Sx
);
1787 newNode
= mkconst_bits(data
, false);
1789 if (children
.size() == 0)
1790 newNode
= current_scope
[str
]->children
[0]->clone();
1792 if (current_scope
[str
]->children
[0]->isConst())
1793 newNode
= current_scope
[str
]->children
[0]->clone();
1795 else if (at_zero
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_WIRE
|| current_scope
[str
]->type
== AST_AUTOWIRE
)) {
1796 newNode
= mkconst_int(0, sign_hint
, width_hint
);
1800 if (children
[0]->type
== AST_CONSTANT
) {
1801 RTLIL::Const y
= RTLIL::const_not(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
1802 newNode
= mkconst_bits(y
.bits
, sign_hint
);
1806 case AST_TO_UNSIGNED
:
1807 if (children
[0]->type
== AST_CONSTANT
) {
1808 RTLIL::Const y
= children
[0]->bitsAsConst(width_hint
, sign_hint
);
1809 newNode
= mkconst_bits(y
.bits
, type
== AST_TO_SIGNED
);
1812 if (0) { case AST_BIT_AND
: const_func
= RTLIL::const_and
; }
1813 if (0) { case AST_BIT_OR
: const_func
= RTLIL::const_or
; }
1814 if (0) { case AST_BIT_XOR
: const_func
= RTLIL::const_xor
; }
1815 if (0) { case AST_BIT_XNOR
: const_func
= RTLIL::const_xnor
; }
1816 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
1817 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
1818 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
1819 newNode
= mkconst_bits(y
.bits
, sign_hint
);
1822 if (0) { case AST_REDUCE_AND
: const_func
= RTLIL::const_reduce_and
; }
1823 if (0) { case AST_REDUCE_OR
: const_func
= RTLIL::const_reduce_or
; }
1824 if (0) { case AST_REDUCE_XOR
: const_func
= RTLIL::const_reduce_xor
; }
1825 if (0) { case AST_REDUCE_XNOR
: const_func
= RTLIL::const_reduce_xnor
; }
1826 if (0) { case AST_REDUCE_BOOL
: const_func
= RTLIL::const_reduce_bool
; }
1827 if (children
[0]->type
== AST_CONSTANT
) {
1828 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), dummy_arg
, false, false, -1);
1829 newNode
= mkconst_bits(y
.bits
, false);
1833 if (children
[0]->type
== AST_CONSTANT
) {
1834 RTLIL::Const y
= RTLIL::const_logic_not(RTLIL::Const(children
[0]->bits
), dummy_arg
, children
[0]->is_signed
, false, -1);
1835 newNode
= mkconst_bits(y
.bits
, false);
1837 if (children
[0]->isConst()) {
1838 newNode
= mkconst_int(children
[0]->asReal(sign_hint
) == 0, false, 1);
1841 if (0) { case AST_LOGIC_AND
: const_func
= RTLIL::const_logic_and
; }
1842 if (0) { case AST_LOGIC_OR
: const_func
= RTLIL::const_logic_or
; }
1843 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
1844 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), RTLIL::Const(children
[1]->bits
),
1845 children
[0]->is_signed
, children
[1]->is_signed
, -1);
1846 newNode
= mkconst_bits(y
.bits
, false);
1848 if (children
[0]->isConst() && children
[1]->isConst()) {
1849 if (type
== AST_LOGIC_AND
)
1850 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) && (children
[1]->asReal(sign_hint
) != 0), false, 1);
1852 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) || (children
[1]->asReal(sign_hint
) != 0), false, 1);
1855 if (0) { case AST_SHIFT_LEFT
: const_func
= RTLIL::const_shl
; }
1856 if (0) { case AST_SHIFT_RIGHT
: const_func
= RTLIL::const_shr
; }
1857 if (0) { case AST_SHIFT_SLEFT
: const_func
= RTLIL::const_sshl
; }
1858 if (0) { case AST_SHIFT_SRIGHT
: const_func
= RTLIL::const_sshr
; }
1859 if (0) { case AST_POW
: const_func
= RTLIL::const_pow
; }
1860 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
1861 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
1862 RTLIL::Const(children
[1]->bits
), sign_hint
, type
== AST_POW
? children
[1]->is_signed
: false, width_hint
);
1863 newNode
= mkconst_bits(y
.bits
, sign_hint
);
1865 if (type
== AST_POW
&& children
[0]->isConst() && children
[1]->isConst()) {
1866 newNode
= new AstNode(AST_REALVALUE
);
1867 newNode
->realvalue
= pow(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
));
1870 if (0) { case AST_LT
: const_func
= RTLIL::const_lt
; }
1871 if (0) { case AST_LE
: const_func
= RTLIL::const_le
; }
1872 if (0) { case AST_EQ
: const_func
= RTLIL::const_eq
; }
1873 if (0) { case AST_NE
: const_func
= RTLIL::const_ne
; }
1874 if (0) { case AST_EQX
: const_func
= RTLIL::const_eqx
; }
1875 if (0) { case AST_NEX
: const_func
= RTLIL::const_nex
; }
1876 if (0) { case AST_GE
: const_func
= RTLIL::const_ge
; }
1877 if (0) { case AST_GT
: const_func
= RTLIL::const_gt
; }
1878 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
1879 int cmp_width
= std::max(children
[0]->bits
.size(), children
[1]->bits
.size());
1880 bool cmp_signed
= children
[0]->is_signed
&& children
[1]->is_signed
;
1881 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(cmp_width
, cmp_signed
),
1882 children
[1]->bitsAsConst(cmp_width
, cmp_signed
), cmp_signed
, cmp_signed
, 1);
1883 newNode
= mkconst_bits(y
.bits
, false);
1885 if (children
[0]->isConst() && children
[1]->isConst()) {
1886 bool cmp_signed
= (children
[0]->type
== AST_REALVALUE
|| children
[0]->is_signed
) && (children
[1]->type
== AST_REALVALUE
|| children
[1]->is_signed
);
1888 case AST_LT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) < children
[1]->asReal(cmp_signed
), false, 1); break;
1889 case AST_LE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) <= children
[1]->asReal(cmp_signed
), false, 1); break;
1890 case AST_EQ
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
1891 case AST_NE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
1892 case AST_EQX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
1893 case AST_NEX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
1894 case AST_GE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) >= children
[1]->asReal(cmp_signed
), false, 1); break;
1895 case AST_GT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) > children
[1]->asReal(cmp_signed
), false, 1); break;
1896 default: log_abort();
1900 if (0) { case AST_ADD
: const_func
= RTLIL::const_add
; }
1901 if (0) { case AST_SUB
: const_func
= RTLIL::const_sub
; }
1902 if (0) { case AST_MUL
: const_func
= RTLIL::const_mul
; }
1903 if (0) { case AST_DIV
: const_func
= RTLIL::const_div
; }
1904 if (0) { case AST_MOD
: const_func
= RTLIL::const_mod
; }
1905 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
1906 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
1907 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
1908 newNode
= mkconst_bits(y
.bits
, sign_hint
);
1910 if (children
[0]->isConst() && children
[1]->isConst()) {
1911 newNode
= new AstNode(AST_REALVALUE
);
1913 case AST_ADD
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) + children
[1]->asReal(sign_hint
); break;
1914 case AST_SUB
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) - children
[1]->asReal(sign_hint
); break;
1915 case AST_MUL
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) * children
[1]->asReal(sign_hint
); break;
1916 case AST_DIV
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) / children
[1]->asReal(sign_hint
); break;
1917 case AST_MOD
: newNode
->realvalue
= fmod(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
)); break;
1918 default: log_abort();
1922 if (0) { case AST_POS
: const_func
= RTLIL::const_pos
; }
1923 if (0) { case AST_NEG
: const_func
= RTLIL::const_neg
; }
1924 if (children
[0]->type
== AST_CONSTANT
) {
1925 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
1926 newNode
= mkconst_bits(y
.bits
, sign_hint
);
1928 if (children
[0]->isConst()) {
1929 newNode
= new AstNode(AST_REALVALUE
);
1930 if (type
== AST_POS
)
1931 newNode
->realvalue
= +children
[0]->asReal(sign_hint
);
1933 newNode
->realvalue
= -children
[0]->asReal(sign_hint
);
1937 if (children
[0]->isConst())
1939 bool found_sure_true
= false;
1940 bool found_maybe_true
= false;
1942 if (children
[0]->type
== AST_CONSTANT
)
1943 for (auto &bit
: children
[0]->bits
) {
1944 if (bit
== RTLIL::State::S1
)
1945 found_sure_true
= true;
1946 if (bit
> RTLIL::State::S1
)
1947 found_maybe_true
= true;
1950 found_sure_true
= children
[0]->asReal(sign_hint
) != 0;
1952 AstNode
*choice
= NULL
, *not_choice
= NULL
;
1953 if (found_sure_true
)
1954 choice
= children
[1], not_choice
= children
[2];
1955 else if (!found_maybe_true
)
1956 choice
= children
[2], not_choice
= children
[1];
1958 if (choice
!= NULL
) {
1959 if (choice
->type
== AST_CONSTANT
) {
1960 int other_width_hint
= width_hint
;
1961 bool other_sign_hint
= sign_hint
, other_real
= false;
1962 not_choice
->detectSignWidth(other_width_hint
, other_sign_hint
, &other_real
);
1964 newNode
= new AstNode(AST_REALVALUE
);
1965 choice
->detectSignWidth(width_hint
, sign_hint
);
1966 newNode
->realvalue
= choice
->asReal(sign_hint
);
1968 RTLIL::Const y
= choice
->bitsAsConst(width_hint
, sign_hint
);
1969 if (choice
->is_string
&& y
.bits
.size() % 8 == 0 && sign_hint
== false)
1970 newNode
= mkconst_str(y
.bits
);
1972 newNode
= mkconst_bits(y
.bits
, sign_hint
);
1975 if (choice
->isConst()) {
1976 newNode
= choice
->clone();
1978 } else if (children
[1]->type
== AST_CONSTANT
&& children
[2]->type
== AST_CONSTANT
) {
1979 RTLIL::Const a
= children
[1]->bitsAsConst(width_hint
, sign_hint
);
1980 RTLIL::Const b
= children
[2]->bitsAsConst(width_hint
, sign_hint
);
1981 log_assert(a
.bits
.size() == b
.bits
.size());
1982 for (size_t i
= 0; i
< a
.bits
.size(); i
++)
1983 if (a
.bits
[i
] != b
.bits
[i
])
1984 a
.bits
[i
] = RTLIL::State::Sx
;
1985 newNode
= mkconst_bits(a
.bits
, sign_hint
);
1986 } else if (children
[1]->isConst() && children
[2]->isConst()) {
1987 newNode
= new AstNode(AST_REALVALUE
);
1988 if (children
[1]->asReal(sign_hint
) == children
[2]->asReal(sign_hint
))
1989 newNode
->realvalue
= children
[1]->asReal(sign_hint
);
1991 // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
1992 // the data type in question should be returned if the ?: is ambiguous. The
1993 // value in Table 7-1 for the 'real' type is 0.0.
1994 newNode
->realvalue
= 0.0;
1999 string_op
= !children
.empty();
2000 for (auto it
= children
.begin(); it
!= children
.end(); it
++) {
2001 if ((*it
)->type
!= AST_CONSTANT
)
2003 if (!(*it
)->is_string
)
2005 tmp_bits
.insert(tmp_bits
.end(), (*it
)->bits
.begin(), (*it
)->bits
.end());
2007 newNode
= string_op
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
2010 if (children
.at(0)->type
!= AST_CONSTANT
|| children
.at(1)->type
!= AST_CONSTANT
)
2012 for (int i
= 0; i
< children
[0]->bitsAsConst().as_int(); i
++)
2013 tmp_bits
.insert(tmp_bits
.end(), children
.at(1)->bits
.begin(), children
.at(1)->bits
.end());
2014 newNode
= children
.at(1)->is_string
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
2022 // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
2025 // fprintf(stderr, "----\n");
2026 // dumpAst(stderr, "- ");
2027 // newNode->dumpAst(stderr, "+ ");
2028 log_assert(newNode
!= NULL
);
2029 newNode
->filename
= filename
;
2030 newNode
->linenum
= linenum
;
2031 newNode
->cloneInto(this);
2033 did_something
= true;
2039 return did_something
;
2042 static void replace_result_wire_name_in_function(AstNode
*node
, std::string
&from
, std::string
&to
)
2044 for (auto &it
: node
->children
)
2045 replace_result_wire_name_in_function(it
, from
, to
);
2046 if (node
->str
== from
)
2050 // replace a readmem[bh] TCALL ast node with a block of memory assignments
2051 AstNode
*AstNode::readmem(bool is_readmemh
, std::string mem_filename
, AstNode
*memory
, int start_addr
, int finish_addr
)
2053 AstNode
*block
= new AstNode(AST_BLOCK
);
2056 f
.open(mem_filename
.c_str());
2059 log_error("Can not open file `%s` for %s at %s:%d.\n", mem_filename
.c_str(), str
.c_str(), filename
.c_str(), linenum
);
2061 log_assert(GetSize(memory
->children
) == 2 && memory
->children
[1]->type
== AST_RANGE
&& memory
->children
[1]->range_valid
);
2062 int range_left
= memory
->children
[1]->range_left
, range_right
= memory
->children
[1]->range_right
;
2063 int range_min
= std::min(range_left
, range_right
), range_max
= std::max(range_left
, range_right
);
2066 start_addr
= range_min
;
2068 if (finish_addr
< 0)
2069 finish_addr
= range_max
;
2071 bool in_comment
= false;
2072 int increment
= start_addr
<= finish_addr
? +1 : -1;
2073 int cursor
= start_addr
;
2077 std::string line
, token
;
2078 std::getline(f
, line
);
2080 for (int i
= 0; i
< GetSize(line
); i
++) {
2081 if (in_comment
&& line
.substr(i
, 2) == "*/") {
2087 if (!in_comment
&& line
.substr(i
, 2) == "/*")
2095 token
= next_token(line
, " \t\r\n");
2096 if (token
.empty() || token
.substr(0, 2) == "//")
2099 if (token
[0] == '@') {
2100 token
= token
.substr(1);
2101 const char *nptr
= token
.c_str();
2103 cursor
= strtol(nptr
, &endptr
, 16);
2104 if (!*nptr
|| *endptr
)
2105 log_error("Can not parse address `%s` for %s at %s:%d.\n", nptr
, str
.c_str(), filename
.c_str(), linenum
);
2109 AstNode
*value
= VERILOG_FRONTEND::const2ast((is_readmemh
? "'h" : "'b") + token
);
2111 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
, false))), value
));
2112 block
->children
.back()->children
[0]->str
= memory
->str
;
2113 block
->children
.back()->children
[0]->id2ast
= memory
;
2115 if ((cursor
== finish_addr
) || (increment
> 0 && cursor
>= range_max
) || (increment
< 0 && cursor
<= range_min
))
2117 cursor
+= increment
;
2120 if ((cursor
== finish_addr
) || (increment
> 0 && cursor
>= range_max
) || (increment
< 0 && cursor
<= range_min
))
2127 // annotate the names of all wires and other named objects in a generate block
2128 void AstNode::expand_genblock(std::string index_var
, std::string prefix
, std::map
<std::string
, std::string
> &name_map
)
2130 if (!index_var
.empty() && type
== AST_IDENTIFIER
&& str
== index_var
) {
2131 current_scope
[index_var
]->children
[0]->cloneInto(this);
2135 if ((type
== AST_IDENTIFIER
|| type
== AST_FCALL
|| type
== AST_TCALL
) && name_map
.count(str
) > 0)
2136 str
= name_map
[str
];
2138 std::map
<std::string
, std::string
> backup_name_map
;
2140 for (size_t i
= 0; i
< children
.size(); i
++) {
2141 AstNode
*child
= children
[i
];
2142 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
||
2143 child
->type
== AST_FUNCTION
|| child
->type
== AST_TASK
|| child
->type
== AST_CELL
) {
2144 if (backup_name_map
.size() == 0)
2145 backup_name_map
= name_map
;
2146 std::string new_name
= prefix
[0] == '\\' ? prefix
.substr(1) : prefix
;
2147 size_t pos
= child
->str
.rfind('.');
2148 if (pos
== std::string::npos
)
2149 pos
= child
->str
[0] == '\\' ? 1 : 0;
2152 new_name
= child
->str
.substr(0, pos
) + new_name
+ child
->str
.substr(pos
);
2153 if (new_name
[0] != '$' && new_name
[0] != '\\')
2154 new_name
= prefix
[0] + new_name
;
2155 name_map
[child
->str
] = new_name
;
2156 if (child
->type
== AST_FUNCTION
)
2157 replace_result_wire_name_in_function(child
, child
->str
, new_name
);
2159 child
->str
= new_name
;
2160 current_scope
[new_name
] = child
;
2164 for (size_t i
= 0; i
< children
.size(); i
++) {
2165 AstNode
*child
= children
[i
];
2166 if (child
->type
!= AST_FUNCTION
&& child
->type
!= AST_TASK
&& child
->type
!= AST_PREFIX
)
2167 child
->expand_genblock(index_var
, prefix
, name_map
);
2170 if (backup_name_map
.size() > 0)
2171 name_map
.swap(backup_name_map
);
2174 // rename stuff (used when tasks of functions are instanciated)
2175 void AstNode::replace_ids(const std::string
&prefix
, const std::map
<std::string
, std::string
> &rules
)
2177 if (type
== AST_BLOCK
)
2179 std::map
<std::string
, std::string
> new_rules
= rules
;
2180 std::string new_prefix
= prefix
+ str
;
2182 for (auto child
: children
)
2183 if (child
->type
== AST_WIRE
) {
2184 new_rules
[child
->str
] = new_prefix
+ child
->str
;
2185 child
->str
= new_prefix
+ child
->str
;
2188 for (auto child
: children
)
2189 if (child
->type
!= AST_WIRE
)
2190 child
->replace_ids(new_prefix
, new_rules
);
2194 if (type
== AST_IDENTIFIER
&& rules
.count(str
) > 0)
2195 str
= rules
.at(str
);
2196 for (auto child
: children
)
2197 child
->replace_ids(prefix
, rules
);
2201 // helper function for mem2reg_as_needed_pass1
2202 static void mark_memories_assign_lhs_complex(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
2203 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, AstNode
*that
)
2205 for (auto &child
: that
->children
)
2206 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, child
);
2208 if (that
->type
== AST_IDENTIFIER
&& that
->id2ast
&& that
->id2ast
->type
== AST_MEMORY
) {
2209 AstNode
*mem
= that
->id2ast
;
2210 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_CMPLX_LHS
))
2211 mem2reg_places
[mem
].insert(stringf("%s:%d", that
->filename
.c_str(), that
->linenum
));
2212 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CMPLX_LHS
;
2216 // find memories that should be replaced by registers
2217 void AstNode::mem2reg_as_needed_pass1(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
2218 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, dict
<AstNode
*, uint32_t> &proc_flags
, uint32_t &flags
)
2220 uint32_t children_flags
= 0;
2221 int ignore_children_counter
= 0;
2223 if (type
== AST_ASSIGN
|| type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
)
2225 // mark all memories that are used in a complex expression on the left side of an assignment
2226 for (auto &lhs_child
: children
[0]->children
)
2227 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, lhs_child
);
2229 if (children
[0]->type
== AST_IDENTIFIER
&& children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
)
2231 AstNode
*mem
= children
[0]->id2ast
;
2233 // activate mem2reg if this is assigned in an async proc
2234 if (flags
& AstNode::MEM2REG_FL_ASYNC
) {
2235 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ASYNC
))
2236 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
2237 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ASYNC
;
2240 // remember if this is assigned blocking (=)
2241 if (type
== AST_ASSIGN_EQ
) {
2242 if (!(proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
))
2243 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
2244 proc_flags
[mem
] |= AstNode::MEM2REG_FL_EQ1
;
2247 // remember where this is
2248 if (flags
& MEM2REG_FL_INIT
) {
2249 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_INIT
))
2250 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
2251 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_INIT
;
2253 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ELSE
))
2254 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
2255 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ELSE
;
2259 ignore_children_counter
= 1;
2262 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
)
2264 AstNode
*mem
= id2ast
;
2266 // flag if used after blocking assignment (in same proc)
2267 if ((proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
) && !(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_EQ2
)) {
2268 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
2269 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_EQ2
;
2273 // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg'
2274 if (type
== AST_MEMORY
&& (get_bool_attribute("\\mem2reg") || (flags
& AstNode::MEM2REG_FL_ALL
) || !is_reg
))
2275 mem2reg_candidates
[this] |= AstNode::MEM2REG_FL_FORCED
;
2277 if (type
== AST_MODULE
&& get_bool_attribute("\\mem2reg"))
2278 children_flags
|= AstNode::MEM2REG_FL_ALL
;
2280 dict
<AstNode
*, uint32_t> *proc_flags_p
= NULL
;
2282 if (type
== AST_ALWAYS
) {
2283 int count_edge_events
= 0;
2284 for (auto child
: children
)
2285 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
2286 count_edge_events
++;
2287 if (count_edge_events
!= 1)
2288 children_flags
|= AstNode::MEM2REG_FL_ASYNC
;
2289 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
2292 if (type
== AST_INITIAL
) {
2293 children_flags
|= AstNode::MEM2REG_FL_INIT
;
2294 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
2297 uint32_t backup_flags
= flags
;
2298 flags
|= children_flags
;
2299 log_assert((flags
& ~0x000000ff) == 0);
2301 for (auto child
: children
)
2302 if (ignore_children_counter
> 0)
2303 ignore_children_counter
--;
2304 else if (proc_flags_p
)
2305 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
2307 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
2309 flags
&= ~children_flags
| backup_flags
;
2312 for (auto it
: *proc_flags_p
)
2313 log_assert((it
.second
& ~0xff000000) == 0);
2314 delete proc_flags_p
;
2318 bool AstNode::mem2reg_check(pool
<AstNode
*> &mem2reg_set
)
2320 if (type
!= AST_IDENTIFIER
|| !id2ast
|| !mem2reg_set
.count(id2ast
))
2323 if (children
.empty() || children
[0]->type
!= AST_RANGE
|| GetSize(children
[0]->children
) != 1)
2324 log_error("Invalid array access at %s:%d.\n", filename
.c_str(), linenum
);
2329 // actually replace memories with registers
2330 void AstNode::mem2reg_as_needed_pass2(pool
<AstNode
*> &mem2reg_set
, AstNode
*mod
, AstNode
*block
)
2332 if (type
== AST_BLOCK
)
2335 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && block
!= NULL
&&
2336 children
[0]->mem2reg_check(mem2reg_set
) && children
[0]->children
[0]->children
[0]->type
!= AST_CONSTANT
)
2338 std::stringstream sstr
;
2339 sstr
<< "$mem2reg_wr$" << children
[0]->str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
2340 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
2342 int mem_width
, mem_size
, addr_bits
;
2343 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
2345 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
2346 wire_addr
->str
= id_addr
;
2347 wire_addr
->is_reg
= true;
2348 wire_addr
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
2349 mod
->children
.push_back(wire_addr
);
2350 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
2352 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
2353 wire_data
->str
= id_data
;
2354 wire_data
->is_reg
= true;
2355 wire_data
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
2356 mod
->children
.push_back(wire_data
);
2357 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
2359 log_assert(block
!= NULL
);
2360 size_t assign_idx
= 0;
2361 while (assign_idx
< block
->children
.size() && block
->children
[assign_idx
] != this)
2363 log_assert(assign_idx
< block
->children
.size());
2365 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
2366 assign_addr
->children
[0]->str
= id_addr
;
2367 block
->children
.insert(block
->children
.begin()+assign_idx
+1, assign_addr
);
2369 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
2370 case_node
->children
[0]->str
= id_addr
;
2371 for (int i
= 0; i
< mem_size
; i
++) {
2372 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->children
[0]->integer
) != i
)
2374 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
2375 AstNode
*assign_reg
= new AstNode(type
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
2376 if (children
[0]->children
.size() == 2)
2377 assign_reg
->children
[0]->children
.push_back(children
[0]->children
[1]->clone());
2378 assign_reg
->children
[0]->str
= stringf("%s[%d]", children
[0]->str
.c_str(), i
);
2379 assign_reg
->children
[1]->str
= id_data
;
2380 cond_node
->children
[1]->children
.push_back(assign_reg
);
2381 case_node
->children
.push_back(cond_node
);
2383 block
->children
.insert(block
->children
.begin()+assign_idx
+2, case_node
);
2385 children
[0]->delete_children();
2386 children
[0]->range_valid
= false;
2387 children
[0]->id2ast
= NULL
;
2388 children
[0]->str
= id_data
;
2389 type
= AST_ASSIGN_EQ
;
2392 if (mem2reg_check(mem2reg_set
))
2394 AstNode
*bit_part_sel
= NULL
;
2395 if (children
.size() == 2)
2396 bit_part_sel
= children
[1]->clone();
2398 if (children
[0]->children
[0]->type
== AST_CONSTANT
)
2400 int id
= children
[0]->children
[0]->integer
;
2401 str
= stringf("%s[%d]", str
.c_str(), id
);
2404 range_valid
= false;
2409 std::stringstream sstr
;
2410 sstr
<< "$mem2reg_rd$" << children
[0]->str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
2411 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
2413 int mem_width
, mem_size
, addr_bits
;
2414 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
2416 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
2417 wire_addr
->str
= id_addr
;
2418 wire_addr
->is_reg
= true;
2420 wire_addr
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
2421 mod
->children
.push_back(wire_addr
);
2422 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
2424 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
2425 wire_data
->str
= id_data
;
2426 wire_data
->is_reg
= true;
2428 wire_data
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
2429 mod
->children
.push_back(wire_data
);
2430 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
2432 AstNode
*assign_addr
= new AstNode(block
? AST_ASSIGN_EQ
: AST_ASSIGN
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->clone());
2433 assign_addr
->children
[0]->str
= id_addr
;
2435 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
2436 case_node
->children
[0]->str
= id_addr
;
2438 for (int i
= 0; i
< mem_size
; i
++) {
2439 if (children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->integer
) != i
)
2441 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
2442 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
2443 assign_reg
->children
[0]->str
= id_data
;
2444 assign_reg
->children
[1]->str
= stringf("%s[%d]", str
.c_str(), i
);
2445 cond_node
->children
[1]->children
.push_back(assign_reg
);
2446 case_node
->children
.push_back(cond_node
);
2449 std::vector
<RTLIL::State
> x_bits
;
2450 for (int i
= 0; i
< mem_width
; i
++)
2451 x_bits
.push_back(RTLIL::State::Sx
);
2453 AstNode
*cond_node
= new AstNode(AST_COND
, new AstNode(AST_DEFAULT
), new AstNode(AST_BLOCK
));
2454 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), AstNode::mkconst_bits(x_bits
, false));
2455 assign_reg
->children
[0]->str
= id_data
;
2456 cond_node
->children
[1]->children
.push_back(assign_reg
);
2457 case_node
->children
.push_back(cond_node
);
2461 size_t assign_idx
= 0;
2462 while (assign_idx
< block
->children
.size() && !block
->children
[assign_idx
]->contains(this))
2464 log_assert(assign_idx
< block
->children
.size());
2465 block
->children
.insert(block
->children
.begin()+assign_idx
, case_node
);
2466 block
->children
.insert(block
->children
.begin()+assign_idx
, assign_addr
);
2470 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
2471 proc
->children
[0]->children
.push_back(case_node
);
2472 mod
->children
.push_back(proc
);
2473 mod
->children
.push_back(assign_addr
);
2477 range_valid
= false;
2483 children
.push_back(bit_part_sel
);
2486 log_assert(id2ast
== NULL
|| mem2reg_set
.count(id2ast
) == 0);
2488 auto children_list
= children
;
2489 for (size_t i
= 0; i
< children_list
.size(); i
++)
2490 children_list
[i
]->mem2reg_as_needed_pass2(mem2reg_set
, mod
, block
);
2493 // calulate memory dimensions
2494 void AstNode::meminfo(int &mem_width
, int &mem_size
, int &addr_bits
)
2496 log_assert(type
== AST_MEMORY
);
2498 mem_width
= children
[0]->range_left
- children
[0]->range_right
+ 1;
2499 mem_size
= children
[1]->range_left
- children
[1]->range_right
;
2503 mem_size
+= std::min(children
[1]->range_left
, children
[1]->range_right
) + 1;
2506 while ((1 << addr_bits
) < mem_size
)
2510 bool AstNode::has_const_only_constructs(bool &recommend_const_eval
)
2512 if (type
== AST_FOR
)
2513 recommend_const_eval
= true;
2514 if (type
== AST_WHILE
|| type
== AST_REPEAT
)
2516 if (type
== AST_FCALL
&& current_scope
.count(str
))
2517 if (current_scope
[str
]->has_const_only_constructs(recommend_const_eval
))
2519 for (auto child
: children
)
2520 if (child
->AstNode::has_const_only_constructs(recommend_const_eval
))
2525 // helper function for AstNode::eval_const_function()
2526 void AstNode::replace_variables(std::map
<std::string
, AstNode::varinfo_t
> &variables
, AstNode
*fcall
)
2528 if (type
== AST_IDENTIFIER
&& variables
.count(str
)) {
2529 int offset
= variables
.at(str
).offset
, width
= variables
.at(str
).val
.bits
.size();
2530 if (!children
.empty()) {
2531 if (children
.size() != 1 || children
.at(0)->type
!= AST_RANGE
)
2532 log_error("Memory access in constant function is not supported in %s:%d (called from %s:%d).\n",
2533 filename
.c_str(), linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
2534 children
.at(0)->replace_variables(variables
, fcall
);
2535 while (simplify(true, false, false, 1, -1, false, true)) { }
2536 if (!children
.at(0)->range_valid
)
2537 log_error("Non-constant range in %s:%d (called from %s:%d).\n",
2538 filename
.c_str(), linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
2539 offset
= std::min(children
.at(0)->range_left
, children
.at(0)->range_right
);
2540 width
= std::min(std::abs(children
.at(0)->range_left
- children
.at(0)->range_right
) + 1, width
);
2542 offset
-= variables
.at(str
).offset
;
2543 std::vector
<RTLIL::State
> &var_bits
= variables
.at(str
).val
.bits
;
2544 std::vector
<RTLIL::State
> new_bits(var_bits
.begin() + offset
, var_bits
.begin() + offset
+ width
);
2545 AstNode
*newNode
= mkconst_bits(new_bits
, variables
.at(str
).is_signed
);
2546 newNode
->cloneInto(this);
2551 for (auto &child
: children
)
2552 child
->replace_variables(variables
, fcall
);
2555 // evaluate functions with all-const arguments
2556 AstNode
*AstNode::eval_const_function(AstNode
*fcall
)
2558 std::map
<std::string
, AstNode
*> backup_scope
;
2559 std::map
<std::string
, AstNode::varinfo_t
> variables
;
2560 bool delete_temp_block
= false;
2561 AstNode
*block
= NULL
;
2564 for (auto child
: children
)
2566 if (child
->type
== AST_BLOCK
)
2568 log_assert(block
== NULL
);
2573 if (child
->type
== AST_WIRE
)
2575 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
2576 if (!child
->range_valid
)
2577 log_error("Can't determine size of variable %s in %s:%d (called from %s:%d).\n",
2578 child
->str
.c_str(), child
->filename
.c_str(), child
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
2579 variables
[child
->str
].val
= RTLIL::Const(RTLIL::State::Sx
, abs(child
->range_left
- child
->range_right
)+1);
2580 variables
[child
->str
].offset
= std::min(child
->range_left
, child
->range_right
);
2581 variables
[child
->str
].is_signed
= child
->is_signed
;
2582 if (child
->is_input
&& argidx
< fcall
->children
.size())
2583 variables
[child
->str
].val
= fcall
->children
.at(argidx
++)->bitsAsConst(variables
[child
->str
].val
.bits
.size());
2584 backup_scope
[child
->str
] = current_scope
[child
->str
];
2585 current_scope
[child
->str
] = child
;
2589 log_assert(block
== NULL
);
2590 delete_temp_block
= true;
2591 block
= new AstNode(AST_BLOCK
);
2592 block
->children
.push_back(child
->clone());
2595 log_assert(block
!= NULL
);
2596 log_assert(variables
.count(str
) != 0);
2598 while (!block
->children
.empty())
2600 AstNode
*stmt
= block
->children
.front();
2603 log("-----------------------------------\n");
2604 for (auto &it
: variables
)
2605 log("%20s %40s\n", it
.first
.c_str(), log_signal(it
.second
.val
));
2606 stmt
->dumpAst(NULL
, "stmt> ");
2609 if (stmt
->type
== AST_ASSIGN_EQ
)
2611 stmt
->children
.at(1)->replace_variables(variables
, fcall
);
2612 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
2614 if (stmt
->type
!= AST_ASSIGN_EQ
)
2617 if (stmt
->children
.at(1)->type
!= AST_CONSTANT
)
2618 log_error("Non-constant expression in constant function at %s:%d (called from %s:%d). X\n",
2619 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
2621 if (stmt
->children
.at(0)->type
!= AST_IDENTIFIER
)
2622 log_error("Unsupported composite left hand side in constant function at %s:%d (called from %s:%d).\n",
2623 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
2625 if (!variables
.count(stmt
->children
.at(0)->str
))
2626 log_error("Assignment to non-local variable in constant function at %s:%d (called from %s:%d).\n",
2627 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
2629 if (stmt
->children
.at(0)->children
.empty()) {
2630 variables
[stmt
->children
.at(0)->str
].val
= stmt
->children
.at(1)->bitsAsConst(variables
[stmt
->children
.at(0)->str
].val
.bits
.size());
2632 AstNode
*range
= stmt
->children
.at(0)->children
.at(0);
2633 if (!range
->range_valid
)
2634 log_error("Non-constant range in %s:%d (called from %s:%d).\n",
2635 range
->filename
.c_str(), range
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
2636 int offset
= std::min(range
->range_left
, range
->range_right
);
2637 int width
= std::abs(range
->range_left
- range
->range_right
) + 1;
2638 varinfo_t
&v
= variables
[stmt
->children
.at(0)->str
];
2639 RTLIL::Const r
= stmt
->children
.at(1)->bitsAsConst(v
.val
.bits
.size());
2640 for (int i
= 0; i
< width
; i
++)
2641 v
.val
.bits
.at(i
+offset
-v
.offset
) = r
.bits
.at(i
);
2644 delete block
->children
.front();
2645 block
->children
.erase(block
->children
.begin());
2649 if (stmt
->type
== AST_FOR
)
2651 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(0));
2652 stmt
->children
.at(3)->children
.push_back(stmt
->children
.at(2));
2653 stmt
->children
.erase(stmt
->children
.begin() + 2);
2654 stmt
->children
.erase(stmt
->children
.begin());
2655 stmt
->type
= AST_WHILE
;
2659 if (stmt
->type
== AST_WHILE
)
2661 AstNode
*cond
= stmt
->children
.at(0)->clone();
2662 cond
->replace_variables(variables
, fcall
);
2663 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
2665 if (cond
->type
!= AST_CONSTANT
)
2666 log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
2667 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
2669 if (cond
->asBool()) {
2670 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
2672 delete block
->children
.front();
2673 block
->children
.erase(block
->children
.begin());
2680 if (stmt
->type
== AST_REPEAT
)
2682 AstNode
*num
= stmt
->children
.at(0)->clone();
2683 num
->replace_variables(variables
, fcall
);
2684 while (num
->simplify(true, false, false, 1, -1, false, true)) { }
2686 if (num
->type
!= AST_CONSTANT
)
2687 log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
2688 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
2690 block
->children
.erase(block
->children
.begin());
2691 for (int i
= 0; i
< num
->bitsAsConst().as_int(); i
++)
2692 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
2699 if (stmt
->type
== AST_CASE
)
2701 AstNode
*expr
= stmt
->children
.at(0)->clone();
2702 expr
->replace_variables(variables
, fcall
);
2703 while (expr
->simplify(true, false, false, 1, -1, false, true)) { }
2705 AstNode
*sel_case
= NULL
;
2706 for (size_t i
= 1; i
< stmt
->children
.size(); i
++)
2708 bool found_match
= false;
2709 log_assert(stmt
->children
.at(i
)->type
== AST_COND
);
2711 if (stmt
->children
.at(i
)->children
.front()->type
== AST_DEFAULT
) {
2712 sel_case
= stmt
->children
.at(i
)->children
.back();
2716 for (size_t j
= 0; j
+1 < stmt
->children
.at(i
)->children
.size() && !found_match
; j
++)
2718 AstNode
*cond
= stmt
->children
.at(i
)->children
.at(j
)->clone();
2719 cond
->replace_variables(variables
, fcall
);
2721 cond
= new AstNode(AST_EQ
, expr
->clone(), cond
);
2722 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
2724 if (cond
->type
!= AST_CONSTANT
)
2725 log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
2726 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
2728 found_match
= cond
->asBool();
2733 sel_case
= stmt
->children
.at(i
)->children
.back();
2738 block
->children
.erase(block
->children
.begin());
2740 block
->children
.insert(block
->children
.begin(), sel_case
->clone());
2746 if (stmt
->type
== AST_BLOCK
)
2748 block
->children
.erase(block
->children
.begin());
2749 block
->children
.insert(block
->children
.begin(), stmt
->children
.begin(), stmt
->children
.end());
2750 stmt
->children
.clear();
2755 log_error("Unsupported language construct in constant function at %s:%d (called from %s:%d).\n",
2756 stmt
->filename
.c_str(), stmt
->linenum
, fcall
->filename
.c_str(), fcall
->linenum
);
2760 if (delete_temp_block
)
2763 for (auto &it
: backup_scope
)
2764 if (it
.second
== NULL
)
2765 current_scope
.erase(it
.first
);
2767 current_scope
[it
.first
] = it
.second
;
2769 return AstNode::mkconst_bits(variables
.at(str
).val
.bits
, variables
.at(str
).is_signed
);