Merge pull request #1670 from rodrigomelo9/master
[yosys.git] / frontends / ast / simplify.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
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.
9 *
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.
17 *
18 * ---
19 *
20 * This is the AST frontend library.
21 *
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.
26 *
27 */
28
29 #include "kernel/log.h"
30 #include "libs/sha1/sha1.h"
31 #include "frontends/verilog/verilog_frontend.h"
32 #include "ast.h"
33
34 #include <sstream>
35 #include <stdarg.h>
36 #include <stdlib.h>
37 #include <math.h>
38
39 YOSYS_NAMESPACE_BEGIN
40
41 using namespace AST;
42 using namespace AST_INTERNAL;
43
44 // Process a format string and arguments for $display, $write, $sprintf, etc
45
46 std::string AstNode::process_format_str(const std::string &sformat, int next_arg, int stage, int width_hint, bool sign_hint) {
47 // Other arguments are placeholders. Process the string as we go through it
48 std::string sout;
49 for (size_t i = 0; i < sformat.length(); i++)
50 {
51 // format specifier
52 if (sformat[i] == '%')
53 {
54 // If there's no next character, that's a problem
55 if (i+1 >= sformat.length())
56 log_file_error(filename, linenum, "System task `%s' called with `%%' at end of string.\n", str.c_str());
57
58 char cformat = sformat[++i];
59
60 // %% is special, does not need a matching argument
61 if (cformat == '%')
62 {
63 sout += '%';
64 continue;
65 }
66
67 // Simplify the argument
68 AstNode *node_arg = nullptr;
69
70 // Everything from here on depends on the format specifier
71 switch (cformat)
72 {
73 case 's':
74 case 'S':
75 case 'd':
76 case 'D':
77 case 'x':
78 case 'X':
79 if (next_arg >= GetSize(children))
80 log_file_error(filename, linenum, "Missing argument for %%%c format specifier in system task `%s'.\n",
81 cformat, str.c_str());
82
83 node_arg = children[next_arg++];
84 while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
85 if (node_arg->type != AST_CONSTANT)
86 log_file_error(filename, linenum, "Failed to evaluate system task `%s' with non-constant argument.\n", str.c_str());
87 break;
88
89 case 'm':
90 case 'M':
91 break;
92
93 default:
94 log_file_error(filename, linenum, "System task `%s' called with invalid/unsupported format specifier.\n", str.c_str());
95 break;
96 }
97
98 switch (cformat)
99 {
100 case 's':
101 case 'S':
102 sout += node_arg->bitsAsConst().decode_string();
103 break;
104
105 case 'd':
106 case 'D':
107 {
108 char tmp[128];
109 snprintf(tmp, sizeof(tmp), "%d", node_arg->bitsAsConst().as_int());
110 sout += tmp;
111 }
112 break;
113
114 case 'x':
115 case 'X':
116 {
117 char tmp[128];
118 snprintf(tmp, sizeof(tmp), "%x", node_arg->bitsAsConst().as_int());
119 sout += tmp;
120 }
121 break;
122
123 case 'm':
124 case 'M':
125 sout += log_id(current_module->name);
126 break;
127
128 default:
129 log_abort();
130 }
131 }
132
133 // not a format specifier
134 else
135 sout += sformat[i];
136 }
137 return sout;
138 }
139
140
141 // convert the AST into a simpler AST that has all parameters substituted by their
142 // values, unrolled for-loops, expanded generate blocks, etc. when this function
143 // is done with an AST it can be converted into RTLIL using genRTLIL().
144 //
145 // this function also does all name resolving and sets the id2ast member of all
146 // nodes that link to a different node using names and lexical scoping.
147 bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
148 {
149 static int recursion_counter = 0;
150 static bool deep_recursion_warning = false;
151
152 if (recursion_counter++ == 1000 && deep_recursion_warning) {
153 log_warning("Deep recursion in AST simplifier.\nDoes this design contain insanely long expressions?\n");
154 deep_recursion_warning = false;
155 }
156
157 AstNode *newNode = NULL;
158 bool did_something = false;
159
160 #if 0
161 log("-------------\n");
162 log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage, recursion_counter, filename.c_str(), linenum, type2str(type).c_str(), this);
163 log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
164 int(const_fold), int(at_zero), int(in_lvalue), int(stage), int(width_hint), int(sign_hint), int(in_param));
165 // dumpAst(NULL, "> ");
166 #endif
167
168 if (stage == 0)
169 {
170 log_assert(type == AST_MODULE || type == AST_INTERFACE);
171
172 deep_recursion_warning = true;
173 while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { }
174
175 if (!flag_nomem2reg && !get_bool_attribute("\\nomem2reg"))
176 {
177 dict<AstNode*, pool<std::string>> mem2reg_places;
178 dict<AstNode*, uint32_t> mem2reg_candidates, dummy_proc_flags;
179 uint32_t flags = flag_mem2reg ? AstNode::MEM2REG_FL_ALL : 0;
180 mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, dummy_proc_flags, flags);
181
182 pool<AstNode*> mem2reg_set;
183 for (auto &it : mem2reg_candidates)
184 {
185 AstNode *mem = it.first;
186 uint32_t memflags = it.second;
187 bool this_nomeminit = flag_nomeminit;
188 log_assert((memflags & ~0x00ffff00) == 0);
189
190 if (mem->get_bool_attribute("\\nomem2reg"))
191 continue;
192
193 if (mem->get_bool_attribute("\\nomeminit") || get_bool_attribute("\\nomeminit"))
194 this_nomeminit = true;
195
196 if (memflags & AstNode::MEM2REG_FL_FORCED)
197 goto silent_activate;
198
199 if (memflags & AstNode::MEM2REG_FL_EQ2)
200 goto verbose_activate;
201
202 if (memflags & AstNode::MEM2REG_FL_SET_ASYNC)
203 goto verbose_activate;
204
205 if ((memflags & AstNode::MEM2REG_FL_SET_INIT) && (memflags & AstNode::MEM2REG_FL_SET_ELSE) && this_nomeminit)
206 goto verbose_activate;
207
208 if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS)
209 goto verbose_activate;
210
211 if ((memflags & AstNode::MEM2REG_FL_CONST_LHS) && !(memflags & AstNode::MEM2REG_FL_VAR_LHS))
212 goto verbose_activate;
213
214 // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
215 continue;
216
217 verbose_activate:
218 if (mem2reg_set.count(mem) == 0) {
219 std::string message = stringf("Replacing memory %s with list of registers.", mem->str.c_str());
220 bool first_element = true;
221 for (auto &place : mem2reg_places[it.first]) {
222 message += stringf("%s%s", first_element ? " See " : ", ", place.c_str());
223 first_element = false;
224 }
225 log_warning("%s\n", message.c_str());
226 }
227
228 silent_activate:
229 // log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
230 mem2reg_set.insert(mem);
231 }
232
233 for (auto node : mem2reg_set)
234 {
235 int mem_width, mem_size, addr_bits;
236 node->meminfo(mem_width, mem_size, addr_bits);
237
238 int data_range_left = node->children[0]->range_left;
239 int data_range_right = node->children[0]->range_right;
240
241 if (node->children[0]->range_swapped)
242 std::swap(data_range_left, data_range_right);
243
244 for (int i = 0; i < mem_size; i++) {
245 AstNode *reg = new AstNode(AST_WIRE, new AstNode(AST_RANGE,
246 mkconst_int(data_range_left, true), mkconst_int(data_range_right, true)));
247 reg->str = stringf("%s[%d]", node->str.c_str(), i);
248 reg->is_reg = true;
249 reg->is_signed = node->is_signed;
250 for (auto &it : node->attributes)
251 if (it.first != ID(mem2reg))
252 reg->attributes.emplace(it.first, it.second->clone());
253 reg->filename = node->filename;
254 reg->linenum = node->linenum;
255 children.push_back(reg);
256 while (reg->simplify(true, false, false, 1, -1, false, false)) { }
257 }
258 }
259
260 AstNode *async_block = NULL;
261 while (mem2reg_as_needed_pass2(mem2reg_set, this, NULL, async_block)) { }
262
263 vector<AstNode*> delnodes;
264 mem2reg_remove(mem2reg_set, delnodes);
265
266 for (auto node : delnodes)
267 delete node;
268 }
269
270 while (simplify(const_fold, at_zero, in_lvalue, 2, width_hint, sign_hint, in_param)) { }
271 recursion_counter--;
272 return false;
273 }
274
275 current_filename = filename;
276 set_line_num(linenum);
277
278 // we do not look inside a task or function
279 // (but as soon as a task or function is instantiated we process the generated AST as usual)
280 if (type == AST_FUNCTION || type == AST_TASK) {
281 recursion_counter--;
282 return false;
283 }
284
285 // deactivate all calls to non-synthesis system tasks
286 // note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
287 if ((type == AST_FCALL || type == AST_TCALL) && (str == "$strobe" || str == "$monitor" || str == "$time" ||
288 str == "$dumpfile" || str == "$dumpvars" || str == "$dumpon" || str == "$dumpoff" || str == "$dumpall")) {
289 log_file_warning(filename, linenum, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str());
290 delete_children();
291 str = std::string();
292 }
293
294 if ((type == AST_TCALL) && (str == "$display" || str == "$write") && (!current_always || current_always->type != AST_INITIAL)) {
295 log_file_warning(filename, linenum, "System task `%s' outside initial block is unsupported.\n", str.c_str());
296 delete_children();
297 str = std::string();
298 }
299
300 // print messages if this a call to $display() or $write()
301 // This code implements only a small subset of Verilog-2005 $display() format specifiers,
302 // but should be good enough for most uses
303 if ((type == AST_TCALL) && ((str == "$display") || (str == "$write")))
304 {
305 int nargs = GetSize(children);
306 if (nargs < 1)
307 log_file_error(filename, linenum, "System task `%s' got %d arguments, expected >= 1.\n",
308 str.c_str(), int(children.size()));
309
310 // First argument is the format string
311 AstNode *node_string = children[0];
312 while (node_string->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
313 if (node_string->type != AST_CONSTANT)
314 log_file_error(filename, linenum, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str.c_str());
315 std::string sformat = node_string->bitsAsConst().decode_string();
316 std::string sout = process_format_str(sformat, 1, stage, width_hint, sign_hint);
317 // Finally, print the message (only include a \n for $display, not for $write)
318 log("%s", sout.c_str());
319 if (str == "$display")
320 log("\n");
321 delete_children();
322 str = std::string();
323 }
324
325 // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
326 if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF)
327 const_fold = true;
328 if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM))
329 const_fold = true;
330
331 // in certain cases a function must be evaluated constant. this is what in_param controls.
332 if (type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_PREFIX)
333 in_param = true;
334
335 std::map<std::string, AstNode*> backup_scope;
336
337 // create name resolution entries for all objects with names
338 // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
339 if (type == AST_MODULE) {
340 current_scope.clear();
341 std::map<std::string, AstNode*> this_wire_scope;
342 for (size_t i = 0; i < children.size(); i++) {
343 AstNode *node = children[i];
344
345 if (node->type == AST_WIRE) {
346 if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
347 for (auto c : node->children[0]->children) {
348 if (!c->is_simple_const_expr()) {
349 if (attributes.count("\\dynports"))
350 delete attributes.at("\\dynports");
351 attributes["\\dynports"] = AstNode::mkconst_int(1, true);
352 }
353 }
354 }
355 if (this_wire_scope.count(node->str) > 0) {
356 AstNode *first_node = this_wire_scope[node->str];
357 if (first_node->is_input && node->is_reg)
358 goto wires_are_incompatible;
359 if (!node->is_input && !node->is_output && node->is_reg && node->children.size() == 0)
360 goto wires_are_compatible;
361 if (first_node->children.size() == 0 && node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
362 AstNode *r = node->children[0];
363 if (r->range_valid && r->range_left == 0 && r->range_right == 0) {
364 delete r;
365 node->children.pop_back();
366 }
367 }
368 if (first_node->children.size() != node->children.size())
369 goto wires_are_incompatible;
370 for (size_t j = 0; j < node->children.size(); j++) {
371 AstNode *n1 = first_node->children[j], *n2 = node->children[j];
372 if (n1->type == AST_RANGE && n2->type == AST_RANGE && n1->range_valid && n2->range_valid) {
373 if (n1->range_left != n2->range_left)
374 goto wires_are_incompatible;
375 if (n1->range_right != n2->range_right)
376 goto wires_are_incompatible;
377 } else if (*n1 != *n2)
378 goto wires_are_incompatible;
379 }
380 if (first_node->range_left != node->range_left)
381 goto wires_are_incompatible;
382 if (first_node->range_right != node->range_right)
383 goto wires_are_incompatible;
384 if (first_node->port_id == 0 && (node->is_input || node->is_output))
385 goto wires_are_incompatible;
386 wires_are_compatible:
387 if (node->is_input)
388 first_node->is_input = true;
389 if (node->is_output)
390 first_node->is_output = true;
391 if (node->is_reg)
392 first_node->is_reg = true;
393 if (node->is_logic)
394 first_node->is_logic = true;
395 if (node->is_signed)
396 first_node->is_signed = true;
397 for (auto &it : node->attributes) {
398 if (first_node->attributes.count(it.first) > 0)
399 delete first_node->attributes[it.first];
400 first_node->attributes[it.first] = it.second->clone();
401 }
402 children.erase(children.begin()+(i--));
403 did_something = true;
404 delete node;
405 continue;
406 wires_are_incompatible:
407 if (stage > 1)
408 log_file_error(filename, linenum, "Incompatible re-declaration of wire %s.\n", node->str.c_str());
409 continue;
410 }
411 this_wire_scope[node->str] = node;
412 }
413 if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
414 node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL ||
415 node->type == AST_TYPEDEF) {
416 backup_scope[node->str] = current_scope[node->str];
417 current_scope[node->str] = node;
418 }
419 }
420 for (size_t i = 0; i < children.size(); i++) {
421 AstNode *node = children[i];
422 if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY || node->type == AST_TYPEDEF)
423 while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM))
424 did_something = true;
425 }
426 }
427
428 auto backup_current_block = current_block;
429 auto backup_current_block_child = current_block_child;
430 auto backup_current_top_block = current_top_block;
431 auto backup_current_always = current_always;
432 auto backup_current_always_clocked = current_always_clocked;
433
434 if (type == AST_ALWAYS || type == AST_INITIAL)
435 {
436 if (current_always != nullptr)
437 log_file_error(filename, linenum, "Invalid nesting of always blocks and/or initializations.\n");
438
439 current_always = this;
440 current_always_clocked = false;
441
442 if (type == AST_ALWAYS)
443 for (auto child : children) {
444 if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE)
445 current_always_clocked = true;
446 if (child->type == AST_EDGE && GetSize(child->children) == 1 &&
447 child->children[0]->type == AST_IDENTIFIER && child->children[0]->str == "\\$global_clock")
448 current_always_clocked = true;
449 }
450 }
451
452 int backup_width_hint = width_hint;
453 bool backup_sign_hint = sign_hint;
454
455 bool detect_width_simple = false;
456 bool child_0_is_self_determined = false;
457 bool child_1_is_self_determined = false;
458 bool child_2_is_self_determined = false;
459 bool children_are_self_determined = false;
460 bool reset_width_after_children = false;
461
462 switch (type)
463 {
464 case AST_ASSIGN_EQ:
465 case AST_ASSIGN_LE:
466 case AST_ASSIGN:
467 while (!children[0]->basic_prep && children[0]->simplify(false, false, true, stage, -1, false, in_param) == true)
468 did_something = true;
469 while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, in_param) == true)
470 did_something = true;
471 children[0]->detectSignWidth(backup_width_hint, backup_sign_hint);
472 children[1]->detectSignWidth(width_hint, sign_hint);
473 width_hint = max(width_hint, backup_width_hint);
474 child_0_is_self_determined = true;
475 // test only once, before optimizations and memory mappings but after assignment LHS was mapped to an identifier
476 if (children[0]->id2ast && !children[0]->was_checked) {
477 if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->id2ast->is_logic)
478 children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment
479 if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg)
480 log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum);
481 if (type == AST_ASSIGN && children[0]->id2ast->is_reg) {
482 bool is_rand_reg = false;
483 if (children[1]->type == AST_FCALL) {
484 if (children[1]->str == "\\$anyconst")
485 is_rand_reg = true;
486 if (children[1]->str == "\\$anyseq")
487 is_rand_reg = true;
488 if (children[1]->str == "\\$allconst")
489 is_rand_reg = true;
490 if (children[1]->str == "\\$allseq")
491 is_rand_reg = true;
492 }
493 if (!is_rand_reg)
494 log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum);
495 }
496 children[0]->was_checked = true;
497 }
498 break;
499
500 case AST_PARAMETER:
501 case AST_LOCALPARAM:
502 while (!children[0]->basic_prep && children[0]->simplify(false, false, false, stage, -1, false, true) == true)
503 did_something = true;
504 children[0]->detectSignWidth(width_hint, sign_hint);
505 if (children.size() > 1 && children[1]->type == AST_RANGE) {
506 while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, true) == true)
507 did_something = true;
508 if (!children[1]->range_valid)
509 log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n");
510 width_hint = max(width_hint, children[1]->range_left - children[1]->range_right + 1);
511 }
512 break;
513
514 case AST_TO_BITS:
515 case AST_TO_SIGNED:
516 case AST_TO_UNSIGNED:
517 case AST_CONCAT:
518 case AST_REPLICATE:
519 case AST_REDUCE_AND:
520 case AST_REDUCE_OR:
521 case AST_REDUCE_XOR:
522 case AST_REDUCE_XNOR:
523 case AST_REDUCE_BOOL:
524 detect_width_simple = true;
525 children_are_self_determined = true;
526 break;
527
528 case AST_NEG:
529 case AST_BIT_NOT:
530 case AST_POS:
531 case AST_BIT_AND:
532 case AST_BIT_OR:
533 case AST_BIT_XOR:
534 case AST_BIT_XNOR:
535 case AST_ADD:
536 case AST_SUB:
537 case AST_MUL:
538 case AST_DIV:
539 case AST_MOD:
540 detect_width_simple = true;
541 break;
542
543 case AST_SHIFT_LEFT:
544 case AST_SHIFT_RIGHT:
545 case AST_SHIFT_SLEFT:
546 case AST_SHIFT_SRIGHT:
547 case AST_POW:
548 detect_width_simple = true;
549 child_1_is_self_determined = true;
550 break;
551
552 case AST_LT:
553 case AST_LE:
554 case AST_EQ:
555 case AST_NE:
556 case AST_EQX:
557 case AST_NEX:
558 case AST_GE:
559 case AST_GT:
560 width_hint = -1;
561 sign_hint = true;
562 for (auto child : children) {
563 while (!child->basic_prep && child->simplify(false, false, in_lvalue, stage, -1, false, in_param) == true)
564 did_something = true;
565 child->detectSignWidthWorker(width_hint, sign_hint);
566 }
567 reset_width_after_children = true;
568 break;
569
570 case AST_LOGIC_AND:
571 case AST_LOGIC_OR:
572 case AST_LOGIC_NOT:
573 detect_width_simple = true;
574 children_are_self_determined = true;
575 break;
576
577 case AST_TERNARY:
578 detect_width_simple = true;
579 child_0_is_self_determined = true;
580 break;
581
582 case AST_MEMRD:
583 detect_width_simple = true;
584 children_are_self_determined = true;
585 break;
586
587 case AST_FCALL:
588 case AST_TCALL:
589 children_are_self_determined = true;
590 break;
591
592 default:
593 width_hint = -1;
594 sign_hint = false;
595 }
596
597 if (detect_width_simple && width_hint < 0) {
598 if (type == AST_REPLICATE)
599 while (children[0]->simplify(true, false, in_lvalue, stage, -1, false, true) == true)
600 did_something = true;
601 for (auto child : children)
602 while (!child->basic_prep && child->simplify(false, false, in_lvalue, stage, -1, false, in_param) == true)
603 did_something = true;
604 detectSignWidth(width_hint, sign_hint);
605 }
606
607 if (type == AST_FCALL && str == "\\$past")
608 detectSignWidth(width_hint, sign_hint);
609
610 if (type == AST_TERNARY) {
611 int width_hint_left, width_hint_right;
612 bool sign_hint_left, sign_hint_right;
613 bool found_real_left, found_real_right;
614 children[1]->detectSignWidth(width_hint_left, sign_hint_left, &found_real_left);
615 children[2]->detectSignWidth(width_hint_right, sign_hint_right, &found_real_right);
616 if (found_real_left || found_real_right) {
617 child_1_is_self_determined = true;
618 child_2_is_self_determined = true;
619 }
620 }
621
622 if (type == AST_CONDX && children.size() > 0 && children.at(0)->type == AST_CONSTANT) {
623 for (auto &bit : children.at(0)->bits)
624 if (bit == State::Sz || bit == State::Sx)
625 bit = State::Sa;
626 }
627
628 if (type == AST_CONDZ && children.size() > 0 && children.at(0)->type == AST_CONSTANT) {
629 for (auto &bit : children.at(0)->bits)
630 if (bit == State::Sz)
631 bit = State::Sa;
632 }
633
634 if (const_fold && type == AST_CASE)
635 {
636 while (children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { }
637 if (children[0]->type == AST_CONSTANT && children[0]->bits_only_01()) {
638 std::vector<AstNode*> new_children;
639 new_children.push_back(children[0]);
640 for (int i = 1; i < GetSize(children); i++) {
641 AstNode *child = children[i];
642 log_assert(child->type == AST_COND || child->type == AST_CONDX || child->type == AST_CONDZ);
643 for (auto v : child->children) {
644 if (v->type == AST_DEFAULT)
645 goto keep_const_cond;
646 if (v->type == AST_BLOCK)
647 continue;
648 while (v->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { }
649 if (v->type == AST_CONSTANT && v->bits_only_01()) {
650 if (v->bits == children[0]->bits) {
651 while (i+1 < GetSize(children))
652 delete children[++i];
653 goto keep_const_cond;
654 }
655 continue;
656 }
657 goto keep_const_cond;
658 }
659 if (0)
660 keep_const_cond:
661 new_children.push_back(child);
662 else
663 delete child;
664 }
665 new_children.swap(children);
666 }
667 }
668
669 // simplify all children first
670 // (iterate by index as e.g. auto wires can add new children in the process)
671 for (size_t i = 0; i < children.size(); i++) {
672 bool did_something_here = true;
673 bool backup_flag_autowire = flag_autowire;
674 if ((type == AST_GENFOR || type == AST_FOR) && i >= 3)
675 break;
676 if ((type == AST_GENIF || type == AST_GENCASE) && i >= 1)
677 break;
678 if (type == AST_GENBLOCK)
679 break;
680 if (type == AST_BLOCK && !str.empty())
681 break;
682 if (type == AST_PREFIX && i >= 1)
683 break;
684 if (type == AST_DEFPARAM && i == 0)
685 flag_autowire = true;
686 while (did_something_here && i < children.size()) {
687 bool const_fold_here = const_fold, in_lvalue_here = in_lvalue;
688 int width_hint_here = width_hint;
689 bool sign_hint_here = sign_hint;
690 bool in_param_here = in_param;
691 if (i == 0 && (type == AST_REPLICATE || type == AST_WIRE))
692 const_fold_here = true, in_param_here = true;
693 if (type == AST_PARAMETER || type == AST_LOCALPARAM)
694 const_fold_here = true;
695 if (i == 0 && (type == AST_ASSIGN || type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE))
696 in_lvalue_here = true;
697 if (type == AST_BLOCK) {
698 current_block = this;
699 current_block_child = children[i];
700 }
701 if ((type == AST_ALWAYS || type == AST_INITIAL) && children[i]->type == AST_BLOCK)
702 current_top_block = children[i];
703 if (i == 0 && child_0_is_self_determined)
704 width_hint_here = -1, sign_hint_here = false;
705 if (i == 1 && child_1_is_self_determined)
706 width_hint_here = -1, sign_hint_here = false;
707 if (i == 2 && child_2_is_self_determined)
708 width_hint_here = -1, sign_hint_here = false;
709 if (children_are_self_determined)
710 width_hint_here = -1, sign_hint_here = false;
711 did_something_here = children[i]->simplify(const_fold_here, at_zero, in_lvalue_here, stage, width_hint_here, sign_hint_here, in_param_here);
712 if (did_something_here)
713 did_something = true;
714 }
715 if (stage == 2 && children[i]->type == AST_INITIAL && current_ast_mod != this) {
716 current_ast_mod->children.push_back(children[i]);
717 children.erase(children.begin() + (i--));
718 did_something = true;
719 }
720 flag_autowire = backup_flag_autowire;
721 }
722 for (auto &attr : attributes) {
723 while (attr.second->simplify(true, false, false, stage, -1, false, true))
724 did_something = true;
725 }
726
727 if (reset_width_after_children) {
728 width_hint = backup_width_hint;
729 sign_hint = backup_sign_hint;
730 if (width_hint < 0)
731 detectSignWidth(width_hint, sign_hint);
732 }
733
734 current_block = backup_current_block;
735 current_block_child = backup_current_block_child;
736 current_top_block = backup_current_top_block;
737 current_always = backup_current_always;
738 current_always_clocked = backup_current_always_clocked;
739
740 for (auto it = backup_scope.begin(); it != backup_scope.end(); it++) {
741 if (it->second == NULL)
742 current_scope.erase(it->first);
743 else
744 current_scope[it->first] = it->second;
745 }
746
747 current_filename = filename;
748 set_line_num(linenum);
749
750 if (type == AST_MODULE)
751 current_scope.clear();
752
753 // convert defparam nodes to cell parameters
754 if (type == AST_DEFPARAM && !children.empty())
755 {
756 if (children[0]->type != AST_IDENTIFIER)
757 log_file_error(filename, linenum, "Module name in defparam contains non-constant expressions!\n");
758
759 string modname, paramname = children[0]->str;
760
761 size_t pos = paramname.rfind('.');
762
763 while (pos != 0 && pos != std::string::npos)
764 {
765 modname = paramname.substr(0, pos);
766
767 if (current_scope.count(modname))
768 break;
769
770 pos = paramname.rfind('.', pos - 1);
771 }
772
773 if (pos == std::string::npos)
774 log_file_error(filename, linenum, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname).c_str());
775
776 paramname = "\\" + paramname.substr(pos+1);
777
778 if (current_scope.at(modname)->type != AST_CELL)
779 log_file_error(filename, linenum, "Defparam argument `%s . %s` does not match a cell!\n",
780 RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str());
781
782 AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL);
783 paraset->str = paramname;
784
785 AstNode *cell = current_scope.at(modname);
786 cell->children.insert(cell->children.begin() + 1, paraset);
787 delete_children();
788 }
789
790 // resolve typedefs
791 if (type == AST_TYPEDEF) {
792 log_assert(children.size() == 1);
793 log_assert(children[0]->type == AST_WIRE || children[0]->type == AST_MEMORY);
794 while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param))
795 did_something = true;
796 log_assert(!children[0]->is_custom_type);
797 }
798
799 // resolve types of wires
800 if (type == AST_WIRE || type == AST_MEMORY) {
801 if (is_custom_type) {
802 log_assert(children.size() >= 1);
803 log_assert(children[0]->type == AST_WIRETYPE);
804 if (!current_scope.count(children[0]->str))
805 log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[0]->str.c_str());
806 AstNode *resolved_type = current_scope.at(children[0]->str);
807 if (resolved_type->type != AST_TYPEDEF)
808 log_file_error(filename, linenum, "`%s' does not name a type\n", children[0]->str.c_str());
809 log_assert(resolved_type->children.size() == 1);
810 AstNode *templ = resolved_type->children[0];
811 // Remove type reference
812 delete children[0];
813 children.erase(children.begin());
814
815 // Ensure typedef itself is fully simplified
816 while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
817
818 if (type == AST_WIRE)
819 type = templ->type;
820 is_reg = templ->is_reg;
821 is_logic = templ->is_logic;
822 is_signed = templ->is_signed;
823 is_string = templ->is_string;
824 is_custom_type = templ->is_custom_type;
825
826 range_valid = templ->range_valid;
827 range_swapped = templ->range_swapped;
828 range_left = templ->range_left;
829 range_right = templ->range_right;
830
831 // Insert clones children from template at beginning
832 for (int i = 0; i < GetSize(templ->children); i++)
833 children.insert(children.begin() + i, templ->children[i]->clone());
834
835 if (type == AST_MEMORY && GetSize(children) == 1) {
836 // Single-bit memories must have [0:0] range
837 AstNode *rng = new AstNode(AST_RANGE);
838 rng->children.push_back(AstNode::mkconst_int(0, true));
839 rng->children.push_back(AstNode::mkconst_int(0, true));
840 children.insert(children.begin(), rng);
841 }
842
843 did_something = true;
844 }
845 log_assert(!is_custom_type);
846 }
847
848 // resolve types of parameters
849 if (type == AST_LOCALPARAM || type == AST_PARAMETER) {
850 if (is_custom_type) {
851 log_assert(children.size() == 2);
852 log_assert(children[1]->type == AST_WIRETYPE);
853 if (!current_scope.count(children[1]->str))
854 log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str());
855 AstNode *resolved_type = current_scope.at(children[1]->str);
856 if (resolved_type->type != AST_TYPEDEF)
857 log_file_error(filename, linenum, "`%s' does not name a type\n", children[1]->str.c_str());
858 log_assert(resolved_type->children.size() == 1);
859 AstNode *templ = resolved_type->children[0];
860 delete children[1];
861 children.pop_back();
862
863 // Ensure typedef itself is fully simplified
864 while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
865
866 if (templ->type == AST_MEMORY)
867 log_file_error(filename, linenum, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str());
868 is_signed = templ->is_signed;
869 is_string = templ->is_string;
870 is_custom_type = templ->is_custom_type;
871
872 range_valid = templ->range_valid;
873 range_swapped = templ->range_swapped;
874 range_left = templ->range_left;
875 range_right = templ->range_right;
876 for (auto template_child : templ->children)
877 children.push_back(template_child->clone());
878 did_something = true;
879 }
880 log_assert(!is_custom_type);
881 }
882
883 // resolve constant prefixes
884 if (type == AST_PREFIX) {
885 if (children[0]->type != AST_CONSTANT) {
886 // dumpAst(NULL, "> ");
887 log_file_error(filename, linenum, "Index in generate block prefix syntax is not constant!\n");
888 }
889 if (children[1]->type == AST_PREFIX)
890 children[1]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param);
891 log_assert(children[1]->type == AST_IDENTIFIER);
892 newNode = children[1]->clone();
893 const char *second_part = children[1]->str.c_str();
894 if (second_part[0] == '\\')
895 second_part++;
896 newNode->str = stringf("%s[%d].%s", str.c_str(), children[0]->integer, second_part);
897 goto apply_newNode;
898 }
899
900 // evaluate TO_BITS nodes
901 if (type == AST_TO_BITS) {
902 if (children[0]->type != AST_CONSTANT)
903 log_file_error(filename, linenum, "Left operand of to_bits expression is not constant!\n");
904 if (children[1]->type != AST_CONSTANT)
905 log_file_error(filename, linenum, "Right operand of to_bits expression is not constant!\n");
906 RTLIL::Const new_value = children[1]->bitsAsConst(children[0]->bitsAsConst().as_int(), children[1]->is_signed);
907 newNode = mkconst_bits(new_value.bits, children[1]->is_signed);
908 goto apply_newNode;
909 }
910
911 // annotate constant ranges
912 if (type == AST_RANGE) {
913 bool old_range_valid = range_valid;
914 range_valid = false;
915 range_swapped = false;
916 range_left = -1;
917 range_right = 0;
918 log_assert(children.size() >= 1);
919 if (children[0]->type == AST_CONSTANT) {
920 range_valid = true;
921 range_left = children[0]->integer;
922 if (children.size() == 1)
923 range_right = range_left;
924 }
925 if (children.size() >= 2) {
926 if (children[1]->type == AST_CONSTANT)
927 range_right = children[1]->integer;
928 else
929 range_valid = false;
930 }
931 if (old_range_valid != range_valid)
932 did_something = true;
933 if (range_valid && range_left >= 0 && range_right > range_left) {
934 int tmp = range_right;
935 range_right = range_left;
936 range_left = tmp;
937 range_swapped = true;
938 }
939 }
940
941 // annotate wires with their ranges
942 if (type == AST_WIRE) {
943 if (children.size() > 0) {
944 if (children[0]->range_valid) {
945 if (!range_valid)
946 did_something = true;
947 range_valid = true;
948 range_swapped = children[0]->range_swapped;
949 range_left = children[0]->range_left;
950 range_right = children[0]->range_right;
951 }
952 } else {
953 if (!range_valid)
954 did_something = true;
955 range_valid = true;
956 range_swapped = false;
957 range_left = 0;
958 range_right = 0;
959 }
960 }
961
962 // resolve multiranges on memory decl
963 if (type == AST_MEMORY && children.size() > 1 && children[1]->type == AST_MULTIRANGE)
964 {
965 int total_size = 1;
966 multirange_dimensions.clear();
967 for (auto range : children[1]->children) {
968 if (!range->range_valid)
969 log_file_error(filename, linenum, "Non-constant range on memory decl.\n");
970 multirange_dimensions.push_back(min(range->range_left, range->range_right));
971 multirange_dimensions.push_back(max(range->range_left, range->range_right) - min(range->range_left, range->range_right) + 1);
972 total_size *= multirange_dimensions.back();
973 }
974 delete children[1];
975 children[1] = new AstNode(AST_RANGE, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size-1, true));
976 did_something = true;
977 }
978
979 // resolve multiranges on memory access
980 if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY && children.size() > 0 && children[0]->type == AST_MULTIRANGE)
981 {
982 AstNode *index_expr = nullptr;
983
984 for (int i = 0; 2*i < GetSize(id2ast->multirange_dimensions); i++)
985 {
986 if (GetSize(children[0]->children) < i)
987 log_file_error(filename, linenum, "Insufficient number of array indices for %s.\n", log_id(str));
988
989 AstNode *new_index_expr = children[0]->children[i]->children.at(0)->clone();
990
991 if (id2ast->multirange_dimensions[2*i])
992 new_index_expr = new AstNode(AST_SUB, new_index_expr, AstNode::mkconst_int(id2ast->multirange_dimensions[2*i], true));
993
994 if (i == 0)
995 index_expr = new_index_expr;
996 else
997 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);
998 }
999
1000 for (int i = GetSize(id2ast->multirange_dimensions)/2; i < GetSize(children[0]->children); i++)
1001 children.push_back(children[0]->children[i]->clone());
1002
1003 delete children[0];
1004 if (index_expr == nullptr)
1005 children.erase(children.begin());
1006 else
1007 children[0] = new AstNode(AST_RANGE, index_expr);
1008
1009 did_something = true;
1010 }
1011
1012 // trim/extend parameters
1013 if (type == AST_PARAMETER || type == AST_LOCALPARAM) {
1014 if (children.size() > 1 && children[1]->type == AST_RANGE) {
1015 if (!children[1]->range_valid)
1016 log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n");
1017 int width = std::abs(children[1]->range_left - children[1]->range_right) + 1;
1018 if (children[0]->type == AST_REALVALUE) {
1019 RTLIL::Const constvalue = children[0]->realAsConst(width);
1020 log_file_warning(filename, linenum, "converting real value %e to binary %s.\n",
1021 children[0]->realvalue, log_signal(constvalue));
1022 delete children[0];
1023 children[0] = mkconst_bits(constvalue.bits, sign_hint);
1024 did_something = true;
1025 }
1026 if (children[0]->type == AST_CONSTANT) {
1027 if (width != int(children[0]->bits.size())) {
1028 RTLIL::SigSpec sig(children[0]->bits);
1029 sig.extend_u0(width, children[0]->is_signed);
1030 AstNode *old_child_0 = children[0];
1031 children[0] = mkconst_bits(sig.as_const().bits, is_signed);
1032 delete old_child_0;
1033 }
1034 children[0]->is_signed = is_signed;
1035 }
1036 range_valid = true;
1037 range_swapped = children[1]->range_swapped;
1038 range_left = children[1]->range_left;
1039 range_right = children[1]->range_right;
1040 } else
1041 if (children.size() > 1 && children[1]->type == AST_REALVALUE && children[0]->type == AST_CONSTANT) {
1042 double as_realvalue = children[0]->asReal(sign_hint);
1043 delete children[0];
1044 children[0] = new AstNode(AST_REALVALUE);
1045 children[0]->realvalue = as_realvalue;
1046 did_something = true;
1047 }
1048 }
1049
1050 // annotate identifiers using scope resolution and create auto-wires as needed
1051 if (type == AST_IDENTIFIER) {
1052 if (current_scope.count(str) == 0) {
1053 for (auto node : current_ast_mod->children) {
1054 if ((node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
1055 node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION) && str == node->str) {
1056 current_scope[node->str] = node;
1057 break;
1058 }
1059 }
1060 }
1061 if (current_scope.count(str) == 0) {
1062 if (flag_autowire || str == "\\$global_clock") {
1063 AstNode *auto_wire = new AstNode(AST_AUTOWIRE);
1064 auto_wire->str = str;
1065 current_ast_mod->children.push_back(auto_wire);
1066 current_scope[str] = auto_wire;
1067 did_something = true;
1068 } else {
1069 log_file_error(filename, linenum, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
1070 }
1071 }
1072 if (id2ast != current_scope[str]) {
1073 id2ast = current_scope[str];
1074 did_something = true;
1075 }
1076 }
1077
1078 // split memory access with bit select to individual statements
1079 if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue)
1080 {
1081 if (id2ast == NULL || id2ast->type != AST_MEMORY || children[0]->children.size() != 1)
1082 log_file_error(filename, linenum, "Invalid bit-select on memory access!\n");
1083
1084 int mem_width, mem_size, addr_bits;
1085 id2ast->meminfo(mem_width, mem_size, addr_bits);
1086
1087 int data_range_left = id2ast->children[0]->range_left;
1088 int data_range_right = id2ast->children[0]->range_right;
1089
1090 if (id2ast->children[0]->range_swapped)
1091 std::swap(data_range_left, data_range_right);
1092
1093 std::stringstream sstr;
1094 sstr << "$mem2bits$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++);
1095 std::string wire_id = sstr.str();
1096
1097 AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(data_range_left, true), mkconst_int(data_range_right, true)));
1098 wire->str = wire_id;
1099 if (current_block)
1100 wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
1101 current_ast_mod->children.push_back(wire);
1102 while (wire->simplify(true, false, false, 1, -1, false, false)) { }
1103
1104 AstNode *data = clone();
1105 delete data->children[1];
1106 data->children.pop_back();
1107
1108 AstNode *assign = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), data);
1109 assign->children[0]->str = wire_id;
1110 assign->children[0]->was_checked = true;
1111
1112 if (current_block)
1113 {
1114 size_t assign_idx = 0;
1115 while (assign_idx < current_block->children.size() && current_block->children[assign_idx] != current_block_child)
1116 assign_idx++;
1117 log_assert(assign_idx < current_block->children.size());
1118 current_block->children.insert(current_block->children.begin()+assign_idx, assign);
1119 wire->is_reg = true;
1120 }
1121 else
1122 {
1123 AstNode *proc = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK));
1124 proc->children[0]->children.push_back(assign);
1125 current_ast_mod->children.push_back(proc);
1126 }
1127
1128 newNode = new AstNode(AST_IDENTIFIER, children[1]->clone());
1129 newNode->str = wire_id;
1130 newNode->id2ast = wire;
1131 goto apply_newNode;
1132 }
1133
1134 if (type == AST_WHILE)
1135 log_file_error(filename, linenum, "While loops are only allowed in constant functions!\n");
1136
1137 if (type == AST_REPEAT)
1138 {
1139 AstNode *count = children[0];
1140 AstNode *body = children[1];
1141
1142 // eval count expression
1143 while (count->simplify(true, false, false, stage, 32, true, false)) { }
1144
1145 if (count->type != AST_CONSTANT)
1146 log_file_error(filename, linenum, "Repeat loops outside must have constant repeat counts!\n");
1147
1148 // convert to a block with the body repeated n times
1149 type = AST_BLOCK;
1150 children.clear();
1151 for (int i = 0; i < count->bitsAsConst().as_int(); i++)
1152 children.insert(children.begin(), body->clone());
1153
1154 delete count;
1155 delete body;
1156 did_something = true;
1157 }
1158
1159 // unroll for loops and generate-for blocks
1160 if ((type == AST_GENFOR || type == AST_FOR) && children.size() != 0)
1161 {
1162 AstNode *init_ast = children[0];
1163 AstNode *while_ast = children[1];
1164 AstNode *next_ast = children[2];
1165 AstNode *body_ast = children[3];
1166
1167 while (body_ast->type == AST_GENBLOCK && body_ast->str.empty() &&
1168 body_ast->children.size() == 1 && body_ast->children.at(0)->type == AST_GENBLOCK)
1169 body_ast = body_ast->children.at(0);
1170
1171 if (init_ast->type != AST_ASSIGN_EQ)
1172 log_file_error(filename, linenum, "Unsupported 1st expression of generate for-loop!\n");
1173 if (next_ast->type != AST_ASSIGN_EQ)
1174 log_file_error(filename, linenum, "Unsupported 3rd expression of generate for-loop!\n");
1175
1176 if (type == AST_GENFOR) {
1177 if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_GENVAR)
1178 log_file_error(filename, linenum, "Left hand side of 1st expression of generate for-loop is not a gen var!\n");
1179 if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_GENVAR)
1180 log_file_error(filename, linenum, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n");
1181 } else {
1182 if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_WIRE)
1183 log_file_error(filename, linenum, "Left hand side of 1st expression of generate for-loop is not a register!\n");
1184 if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_WIRE)
1185 log_file_error(filename, linenum, "Left hand side of 3rd expression of generate for-loop is not a register!\n");
1186 }
1187
1188 if (init_ast->children[0]->id2ast != next_ast->children[0]->id2ast)
1189 log_file_error(filename, linenum, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n");
1190
1191 // eval 1st expression
1192 AstNode *varbuf = init_ast->children[1]->clone();
1193 {
1194 int expr_width_hint = -1;
1195 bool expr_sign_hint = true;
1196 varbuf->detectSignWidth(expr_width_hint, expr_sign_hint);
1197 while (varbuf->simplify(true, false, false, stage, 32, true, false)) { }
1198 }
1199
1200 if (varbuf->type != AST_CONSTANT)
1201 log_file_error(filename, linenum, "Right hand side of 1st expression of generate for-loop is not constant!\n");
1202
1203 varbuf = new AstNode(AST_LOCALPARAM, varbuf);
1204 varbuf->str = init_ast->children[0]->str;
1205
1206 auto resolved = current_scope.at(init_ast->children[0]->str);
1207 if (resolved->range_valid) {
1208 varbuf->range_left = resolved->range_left;
1209 varbuf->range_right = resolved->range_right;
1210 varbuf->range_swapped = resolved->range_swapped;
1211 varbuf->range_valid = resolved->range_valid;
1212 }
1213
1214 AstNode *backup_scope_varbuf = current_scope[varbuf->str];
1215 current_scope[varbuf->str] = varbuf;
1216
1217 size_t current_block_idx = 0;
1218 if (type == AST_FOR) {
1219 while (current_block_idx < current_block->children.size() &&
1220 current_block->children[current_block_idx] != current_block_child)
1221 current_block_idx++;
1222 }
1223
1224 while (1)
1225 {
1226 // eval 2nd expression
1227 AstNode *buf = while_ast->clone();
1228 {
1229 int expr_width_hint = -1;
1230 bool expr_sign_hint = true;
1231 buf->detectSignWidth(expr_width_hint, expr_sign_hint);
1232 while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, false)) { }
1233 }
1234
1235 if (buf->type != AST_CONSTANT)
1236 log_file_error(filename, linenum, "2nd expression of generate for-loop is not constant!\n");
1237
1238 if (buf->integer == 0) {
1239 delete buf;
1240 break;
1241 }
1242 delete buf;
1243
1244 // expand body
1245 int index = varbuf->children[0]->integer;
1246 if (body_ast->type == AST_GENBLOCK)
1247 buf = body_ast->clone();
1248 else
1249 buf = new AstNode(AST_GENBLOCK, body_ast->clone());
1250 if (buf->str.empty()) {
1251 std::stringstream sstr;
1252 sstr << "$genblock$" << filename << ":" << linenum << "$" << (autoidx++);
1253 buf->str = sstr.str();
1254 }
1255 std::map<std::string, std::string> name_map;
1256 std::stringstream sstr;
1257 sstr << buf->str << "[" << index << "].";
1258 buf->expand_genblock(varbuf->str, sstr.str(), name_map);
1259
1260 if (type == AST_GENFOR) {
1261 for (size_t i = 0; i < buf->children.size(); i++) {
1262 buf->children[i]->simplify(false, false, false, stage, -1, false, false);
1263 current_ast_mod->children.push_back(buf->children[i]);
1264 }
1265 } else {
1266 for (size_t i = 0; i < buf->children.size(); i++)
1267 current_block->children.insert(current_block->children.begin() + current_block_idx++, buf->children[i]);
1268 }
1269 buf->children.clear();
1270 delete buf;
1271
1272 // eval 3rd expression
1273 buf = next_ast->children[1]->clone();
1274 {
1275 int expr_width_hint = -1;
1276 bool expr_sign_hint = true;
1277 buf->detectSignWidth(expr_width_hint, expr_sign_hint);
1278 while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, true)) { }
1279 }
1280
1281 if (buf->type != AST_CONSTANT)
1282 log_file_error(filename, linenum, "Right hand side of 3rd expression of generate for-loop is not constant!\n");
1283
1284 delete varbuf->children[0];
1285 varbuf->children[0] = buf;
1286 }
1287
1288 if (type == AST_FOR) {
1289 AstNode *buf = next_ast->clone();
1290 delete buf->children[1];
1291 buf->children[1] = varbuf->children[0]->clone();
1292 current_block->children.insert(current_block->children.begin() + current_block_idx++, buf);
1293 }
1294
1295 current_scope[varbuf->str] = backup_scope_varbuf;
1296 delete varbuf;
1297 delete_children();
1298 did_something = true;
1299 }
1300
1301 // check for local objects in unnamed block
1302 if (type == AST_BLOCK && str.empty())
1303 {
1304 for (size_t i = 0; i < children.size(); i++)
1305 if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF)
1306 log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
1307 }
1308
1309 // transform block with name
1310 if (type == AST_BLOCK && !str.empty())
1311 {
1312 std::map<std::string, std::string> name_map;
1313 expand_genblock(std::string(), str + ".", name_map);
1314
1315 std::vector<AstNode*> new_children;
1316 for (size_t i = 0; i < children.size(); i++)
1317 if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) {
1318 children[i]->simplify(false, false, false, stage, -1, false, false);
1319 current_ast_mod->children.push_back(children[i]);
1320 current_scope[children[i]->str] = children[i];
1321 } else
1322 new_children.push_back(children[i]);
1323
1324 children.swap(new_children);
1325 did_something = true;
1326 str.clear();
1327 }
1328
1329 // simplify unconditional generate block
1330 if (type == AST_GENBLOCK && children.size() != 0)
1331 {
1332 if (!str.empty()) {
1333 std::map<std::string, std::string> name_map;
1334 expand_genblock(std::string(), str + ".", name_map);
1335 }
1336
1337 for (size_t i = 0; i < children.size(); i++) {
1338 children[i]->simplify(false, false, false, stage, -1, false, false);
1339 current_ast_mod->children.push_back(children[i]);
1340 }
1341
1342 children.clear();
1343 did_something = true;
1344 }
1345
1346 // simplify generate-if blocks
1347 if (type == AST_GENIF && children.size() != 0)
1348 {
1349 AstNode *buf = children[0]->clone();
1350 while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1351 if (buf->type != AST_CONSTANT) {
1352 // for (auto f : log_files)
1353 // dumpAst(f, "verilog-ast> ");
1354 log_file_error(filename, linenum, "Condition for generate if is not constant!\n");
1355 }
1356 if (buf->asBool() != 0) {
1357 delete buf;
1358 buf = children[1]->clone();
1359 } else {
1360 delete buf;
1361 buf = children.size() > 2 ? children[2]->clone() : NULL;
1362 }
1363
1364 if (buf)
1365 {
1366 if (buf->type != AST_GENBLOCK)
1367 buf = new AstNode(AST_GENBLOCK, buf);
1368
1369 if (!buf->str.empty()) {
1370 std::map<std::string, std::string> name_map;
1371 buf->expand_genblock(std::string(), buf->str + ".", name_map);
1372 }
1373
1374 for (size_t i = 0; i < buf->children.size(); i++) {
1375 buf->children[i]->simplify(false, false, false, stage, -1, false, false);
1376 current_ast_mod->children.push_back(buf->children[i]);
1377 }
1378
1379 buf->children.clear();
1380 delete buf;
1381 }
1382
1383 delete_children();
1384 did_something = true;
1385 }
1386
1387 // simplify generate-case blocks
1388 if (type == AST_GENCASE && children.size() != 0)
1389 {
1390 AstNode *buf = children[0]->clone();
1391 while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1392 if (buf->type != AST_CONSTANT) {
1393 // for (auto f : log_files)
1394 // dumpAst(f, "verilog-ast> ");
1395 log_file_error(filename, linenum, "Condition for generate case is not constant!\n");
1396 }
1397
1398 bool ref_signed = buf->is_signed;
1399 RTLIL::Const ref_value = buf->bitsAsConst();
1400 delete buf;
1401
1402 AstNode *selected_case = NULL;
1403 for (size_t i = 1; i < children.size(); i++)
1404 {
1405 log_assert(children.at(i)->type == AST_COND || children.at(i)->type == AST_CONDX || children.at(i)->type == AST_CONDZ);
1406
1407 AstNode *this_genblock = NULL;
1408 for (auto child : children.at(i)->children) {
1409 log_assert(this_genblock == NULL);
1410 if (child->type == AST_GENBLOCK)
1411 this_genblock = child;
1412 }
1413
1414 for (auto child : children.at(i)->children)
1415 {
1416 if (child->type == AST_DEFAULT) {
1417 if (selected_case == NULL)
1418 selected_case = this_genblock;
1419 continue;
1420 }
1421 if (child->type == AST_GENBLOCK)
1422 continue;
1423
1424 buf = child->clone();
1425 while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1426 if (buf->type != AST_CONSTANT) {
1427 // for (auto f : log_files)
1428 // dumpAst(f, "verilog-ast> ");
1429 log_file_error(filename, linenum, "Expression in generate case is not constant!\n");
1430 }
1431
1432 bool is_selected = RTLIL::const_eq(ref_value, buf->bitsAsConst(), ref_signed && buf->is_signed, ref_signed && buf->is_signed, 1).as_bool();
1433 delete buf;
1434
1435 if (is_selected) {
1436 selected_case = this_genblock;
1437 i = children.size();
1438 break;
1439 }
1440 }
1441 }
1442
1443 if (selected_case != NULL)
1444 {
1445 log_assert(selected_case->type == AST_GENBLOCK);
1446 buf = selected_case->clone();
1447
1448 if (!buf->str.empty()) {
1449 std::map<std::string, std::string> name_map;
1450 buf->expand_genblock(std::string(), buf->str + ".", name_map);
1451 }
1452
1453 for (size_t i = 0; i < buf->children.size(); i++) {
1454 buf->children[i]->simplify(false, false, false, stage, -1, false, false);
1455 current_ast_mod->children.push_back(buf->children[i]);
1456 }
1457
1458 buf->children.clear();
1459 delete buf;
1460 }
1461
1462 delete_children();
1463 did_something = true;
1464 }
1465
1466 // unroll cell arrays
1467 if (type == AST_CELLARRAY)
1468 {
1469 if (!children.at(0)->range_valid)
1470 log_file_error(filename, linenum, "Non-constant array range on cell array.\n");
1471
1472 newNode = new AstNode(AST_GENBLOCK);
1473 int num = max(children.at(0)->range_left, children.at(0)->range_right) - min(children.at(0)->range_left, children.at(0)->range_right) + 1;
1474
1475 for (int i = 0; i < num; i++) {
1476 int idx = children.at(0)->range_left > children.at(0)->range_right ? children.at(0)->range_right + i : children.at(0)->range_right - i;
1477 AstNode *new_cell = children.at(1)->clone();
1478 newNode->children.push_back(new_cell);
1479 new_cell->str += stringf("[%d]", idx);
1480 if (new_cell->type == AST_PRIMITIVE) {
1481 log_file_error(filename, linenum, "Cell arrays of primitives are currently not supported.\n");
1482 } else {
1483 log_assert(new_cell->children.at(0)->type == AST_CELLTYPE);
1484 new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str.c_str());
1485 }
1486 }
1487
1488 goto apply_newNode;
1489 }
1490
1491 // replace primitives with assignments
1492 if (type == AST_PRIMITIVE)
1493 {
1494 if (children.size() < 2)
1495 log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", str.c_str());
1496
1497 std::vector<AstNode*> children_list;
1498 for (auto child : children) {
1499 log_assert(child->type == AST_ARGUMENT);
1500 log_assert(child->children.size() == 1);
1501 children_list.push_back(child->children[0]);
1502 child->children.clear();
1503 delete child;
1504 }
1505 children.clear();
1506
1507 if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1")
1508 {
1509 if (children_list.size() != 3)
1510 log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", str.c_str());
1511
1512 std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz);
1513
1514 AstNode *mux_input = children_list.at(1);
1515 if (str == "notif0" || str == "notif1") {
1516 mux_input = new AstNode(AST_BIT_NOT, mux_input);
1517 }
1518 AstNode *node = new AstNode(AST_TERNARY, children_list.at(2));
1519 if (str == "bufif0") {
1520 node->children.push_back(AstNode::mkconst_bits(z_const, false));
1521 node->children.push_back(mux_input);
1522 } else {
1523 node->children.push_back(mux_input);
1524 node->children.push_back(AstNode::mkconst_bits(z_const, false));
1525 }
1526
1527 str.clear();
1528 type = AST_ASSIGN;
1529 children.push_back(children_list.at(0));
1530 children.back()->was_checked = true;
1531 children.push_back(node);
1532 did_something = true;
1533 }
1534 else
1535 {
1536 AstNodeType op_type = AST_NONE;
1537 bool invert_results = false;
1538
1539 if (str == "and")
1540 op_type = AST_BIT_AND;
1541 if (str == "nand")
1542 op_type = AST_BIT_AND, invert_results = true;
1543 if (str == "or")
1544 op_type = AST_BIT_OR;
1545 if (str == "nor")
1546 op_type = AST_BIT_OR, invert_results = true;
1547 if (str == "xor")
1548 op_type = AST_BIT_XOR;
1549 if (str == "xnor")
1550 op_type = AST_BIT_XOR, invert_results = true;
1551 if (str == "buf")
1552 op_type = AST_POS;
1553 if (str == "not")
1554 op_type = AST_POS, invert_results = true;
1555 log_assert(op_type != AST_NONE);
1556
1557 AstNode *node = children_list[1];
1558 if (op_type != AST_POS)
1559 for (size_t i = 2; i < children_list.size(); i++)
1560 node = new AstNode(op_type, node, children_list[i]);
1561 if (invert_results)
1562 node = new AstNode(AST_BIT_NOT, node);
1563
1564 str.clear();
1565 type = AST_ASSIGN;
1566 children.push_back(children_list[0]);
1567 children.back()->was_checked = true;
1568 children.push_back(node);
1569 did_something = true;
1570 }
1571 }
1572
1573 // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
1574 // a big case block that selects the correct single-bit assignment.
1575 if (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) {
1576 if (children[0]->type != AST_IDENTIFIER || children[0]->children.size() == 0)
1577 goto skip_dynamic_range_lvalue_expansion;
1578 if (children[0]->children[0]->range_valid || did_something)
1579 goto skip_dynamic_range_lvalue_expansion;
1580 if (children[0]->id2ast == NULL || children[0]->id2ast->type != AST_WIRE)
1581 goto skip_dynamic_range_lvalue_expansion;
1582 if (!children[0]->id2ast->range_valid)
1583 goto skip_dynamic_range_lvalue_expansion;
1584 int source_width = children[0]->id2ast->range_left - children[0]->id2ast->range_right + 1;
1585 int result_width = 1;
1586 AstNode *shift_expr = NULL;
1587 AstNode *range = children[0]->children[0];
1588 if (range->children.size() == 1) {
1589 shift_expr = range->children[0]->clone();
1590 } else {
1591 shift_expr = range->children[1]->clone();
1592 AstNode *left_at_zero_ast = range->children[0]->clone();
1593 AstNode *right_at_zero_ast = range->children[1]->clone();
1594 while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
1595 while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
1596 if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
1597 log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
1598 result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
1599 }
1600 did_something = true;
1601 newNode = new AstNode(AST_CASE, shift_expr);
1602 for (int i = 0; i <= source_width-result_width; i++) {
1603 int start_bit = children[0]->id2ast->range_right + i;
1604 AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true));
1605 AstNode *lvalue = children[0]->clone();
1606 lvalue->delete_children();
1607 lvalue->children.push_back(new AstNode(AST_RANGE,
1608 mkconst_int(start_bit+result_width-1, true), mkconst_int(start_bit, true)));
1609 cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone())));
1610 newNode->children.push_back(cond);
1611 }
1612 goto apply_newNode;
1613 }
1614 skip_dynamic_range_lvalue_expansion:;
1615
1616 if (stage > 1 && (type == AST_ASSERT || type == AST_ASSUME || type == AST_LIVE || type == AST_FAIR || type == AST_COVER) && current_block != NULL)
1617 {
1618 std::stringstream sstr;
1619 sstr << "$formal$" << filename << ":" << linenum << "$" << (autoidx++);
1620 std::string id_check = sstr.str() + "_CHECK", id_en = sstr.str() + "_EN";
1621
1622 AstNode *wire_check = new AstNode(AST_WIRE);
1623 wire_check->str = id_check;
1624 wire_check->was_checked = true;
1625 current_ast_mod->children.push_back(wire_check);
1626 current_scope[wire_check->str] = wire_check;
1627 while (wire_check->simplify(true, false, false, 1, -1, false, false)) { }
1628
1629 AstNode *wire_en = new AstNode(AST_WIRE);
1630 wire_en->str = id_en;
1631 wire_en->was_checked = true;
1632 current_ast_mod->children.push_back(wire_en);
1633 if (current_always_clocked) {
1634 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)))));
1635 current_ast_mod->children.back()->children[0]->children[0]->children[0]->str = id_en;
1636 current_ast_mod->children.back()->children[0]->children[0]->children[0]->was_checked = true;
1637 }
1638 current_scope[wire_en->str] = wire_en;
1639 while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
1640
1641 AstNode *check_defval;
1642 if (type == AST_LIVE || type == AST_FAIR) {
1643 check_defval = new AstNode(AST_REDUCE_BOOL, children[0]->clone());
1644 } else {
1645 std::vector<RTLIL::State> x_bit;
1646 x_bit.push_back(RTLIL::State::Sx);
1647 check_defval = mkconst_bits(x_bit, false);
1648 }
1649
1650 AstNode *assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), check_defval);
1651 assign_check->children[0]->str = id_check;
1652 assign_check->children[0]->was_checked = true;
1653
1654 AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, 1));
1655 assign_en->children[0]->str = id_en;
1656 assign_en->children[0]->was_checked = true;
1657
1658 AstNode *default_signals = new AstNode(AST_BLOCK);
1659 default_signals->children.push_back(assign_check);
1660 default_signals->children.push_back(assign_en);
1661 current_top_block->children.insert(current_top_block->children.begin(), default_signals);
1662
1663 if (type == AST_LIVE || type == AST_FAIR) {
1664 assign_check = nullptr;
1665 } else {
1666 assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_REDUCE_BOOL, children[0]->clone()));
1667 assign_check->children[0]->str = id_check;
1668 assign_check->children[0]->was_checked = true;
1669 }
1670
1671 if (current_always == nullptr || current_always->type != AST_INITIAL) {
1672 assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(1, false, 1));
1673 } else {
1674 assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_FCALL));
1675 assign_en->children[1]->str = "\\$initstate";
1676 }
1677 assign_en->children[0]->str = id_en;
1678 assign_en->children[0]->was_checked = true;
1679
1680 newNode = new AstNode(AST_BLOCK);
1681 if (assign_check != nullptr)
1682 newNode->children.push_back(assign_check);
1683 newNode->children.push_back(assign_en);
1684
1685 AstNode *assertnode = new AstNode(type);
1686 assertnode->str = str;
1687 assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
1688 assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
1689 assertnode->children[0]->str = id_check;
1690 assertnode->children[1]->str = id_en;
1691 assertnode->attributes.swap(attributes);
1692 current_ast_mod->children.push_back(assertnode);
1693
1694 goto apply_newNode;
1695 }
1696
1697 if (stage > 1 && (type == AST_ASSERT || type == AST_ASSUME || type == AST_LIVE || type == AST_FAIR || type == AST_COVER) && children.size() == 1)
1698 {
1699 children.push_back(mkconst_int(1, false, 1));
1700 did_something = true;
1701 }
1702
1703 // found right-hand side identifier for memory -> replace with memory read port
1704 if (stage > 1 && type == AST_IDENTIFIER && id2ast != NULL && id2ast->type == AST_MEMORY && !in_lvalue &&
1705 children.size() == 1 && children[0]->type == AST_RANGE && children[0]->children.size() == 1) {
1706 newNode = new AstNode(AST_MEMRD, children[0]->children[0]->clone());
1707 newNode->str = str;
1708 newNode->id2ast = id2ast;
1709 goto apply_newNode;
1710 }
1711
1712 // assignment with nontrivial member in left-hand concat expression -> split assignment
1713 if ((type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) && children[0]->type == AST_CONCAT && width_hint > 0)
1714 {
1715 bool found_nontrivial_member = false;
1716
1717 for (auto child : children[0]->children) {
1718 if (child->type == AST_IDENTIFIER && child->id2ast != NULL && child->id2ast->type == AST_MEMORY)
1719 found_nontrivial_member = true;
1720 }
1721
1722 if (found_nontrivial_member)
1723 {
1724 newNode = new AstNode(AST_BLOCK);
1725
1726 AstNode *wire_tmp = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(width_hint-1, true), mkconst_int(0, true)));
1727 wire_tmp->str = stringf("$splitcmplxassign$%s:%d$%d", filename.c_str(), linenum, autoidx++);
1728 current_ast_mod->children.push_back(wire_tmp);
1729 current_scope[wire_tmp->str] = wire_tmp;
1730 wire_tmp->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
1731 while (wire_tmp->simplify(true, false, false, 1, -1, false, false)) { }
1732 wire_tmp->is_logic = true;
1733
1734 AstNode *wire_tmp_id = new AstNode(AST_IDENTIFIER);
1735 wire_tmp_id->str = wire_tmp->str;
1736
1737 newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, wire_tmp_id, children[1]->clone()));
1738 newNode->children.back()->was_checked = true;
1739
1740 int cursor = 0;
1741 for (auto child : children[0]->children)
1742 {
1743 int child_width_hint = -1;
1744 bool child_sign_hint = true;
1745 child->detectSignWidth(child_width_hint, child_sign_hint);
1746
1747 AstNode *rhs = wire_tmp_id->clone();
1748 rhs->children.push_back(new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+child_width_hint-1, true), AstNode::mkconst_int(cursor, true)));
1749 newNode->children.push_back(new AstNode(type, child->clone(), rhs));
1750
1751 cursor += child_width_hint;
1752 }
1753
1754 goto apply_newNode;
1755 }
1756 }
1757
1758 // assignment with memory in left-hand side expression -> replace with memory write port
1759 if (stage > 1 && (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) && children[0]->type == AST_IDENTIFIER &&
1760 children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY && children[0]->id2ast->children.size() >= 2 &&
1761 children[0]->id2ast->children[0]->range_valid && children[0]->id2ast->children[1]->range_valid &&
1762 (children[0]->children.size() == 1 || children[0]->children.size() == 2) && children[0]->children[0]->type == AST_RANGE)
1763 {
1764 std::stringstream sstr;
1765 sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
1766 std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN";
1767
1768 int mem_width, mem_size, addr_bits;
1769 bool mem_signed = children[0]->id2ast->is_signed;
1770 children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
1771
1772 int data_range_left = children[0]->id2ast->children[0]->range_left;
1773 int data_range_right = children[0]->id2ast->children[0]->range_right;
1774 int mem_data_range_offset = std::min(data_range_left, data_range_right);
1775
1776 int addr_width_hint = -1;
1777 bool addr_sign_hint = true;
1778 children[0]->children[0]->children[0]->detectSignWidthWorker(addr_width_hint, addr_sign_hint);
1779 addr_bits = std::max(addr_bits, addr_width_hint);
1780
1781 AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
1782 wire_addr->str = id_addr;
1783 wire_addr->was_checked = true;
1784 current_ast_mod->children.push_back(wire_addr);
1785 current_scope[wire_addr->str] = wire_addr;
1786 while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
1787
1788 AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
1789 wire_data->str = id_data;
1790 wire_data->was_checked = true;
1791 wire_data->is_signed = mem_signed;
1792 current_ast_mod->children.push_back(wire_data);
1793 current_scope[wire_data->str] = wire_data;
1794 while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
1795
1796 AstNode *wire_en = nullptr;
1797 if (current_always->type != AST_INITIAL) {
1798 wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
1799 wire_en->str = id_en;
1800 wire_en->was_checked = true;
1801 current_ast_mod->children.push_back(wire_en);
1802 current_scope[wire_en->str] = wire_en;
1803 while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
1804 }
1805
1806 std::vector<RTLIL::State> x_bits_addr, x_bits_data, set_bits_en;
1807 for (int i = 0; i < addr_bits; i++)
1808 x_bits_addr.push_back(RTLIL::State::Sx);
1809 for (int i = 0; i < mem_width; i++)
1810 x_bits_data.push_back(RTLIL::State::Sx);
1811 for (int i = 0; i < mem_width; i++)
1812 set_bits_en.push_back(RTLIL::State::S1);
1813
1814 AstNode *assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false));
1815 assign_addr->children[0]->str = id_addr;
1816 assign_addr->children[0]->was_checked = true;
1817
1818 AstNode *assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false));
1819 assign_data->children[0]->str = id_data;
1820 assign_data->children[0]->was_checked = true;
1821
1822 AstNode *assign_en = nullptr;
1823 if (current_always->type != AST_INITIAL) {
1824 assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width));
1825 assign_en->children[0]->str = id_en;
1826 assign_en->children[0]->was_checked = true;
1827 }
1828
1829 AstNode *default_signals = new AstNode(AST_BLOCK);
1830 default_signals->children.push_back(assign_addr);
1831 default_signals->children.push_back(assign_data);
1832 if (current_always->type != AST_INITIAL)
1833 default_signals->children.push_back(assign_en);
1834 current_top_block->children.insert(current_top_block->children.begin(), default_signals);
1835
1836 assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
1837 assign_addr->children[0]->str = id_addr;
1838 assign_addr->children[0]->was_checked = true;
1839
1840 if (children[0]->children.size() == 2)
1841 {
1842 if (children[0]->children[1]->range_valid)
1843 {
1844 int offset = children[0]->children[1]->range_right;
1845 int width = children[0]->children[1]->range_left - offset + 1;
1846 offset -= mem_data_range_offset;
1847
1848 std::vector<RTLIL::State> padding_x(offset, RTLIL::State::Sx);
1849
1850 assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
1851 new AstNode(AST_CONCAT, mkconst_bits(padding_x, false), children[1]->clone()));
1852 assign_data->children[0]->str = id_data;
1853 assign_data->children[0]->was_checked = true;
1854
1855 if (current_always->type != AST_INITIAL) {
1856 for (int i = 0; i < mem_width; i++)
1857 set_bits_en[i] = offset <= i && i < offset+width ? RTLIL::State::S1 : RTLIL::State::S0;
1858 assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
1859 assign_en->children[0]->str = id_en;
1860 assign_en->children[0]->was_checked = true;
1861 }
1862 }
1863 else
1864 {
1865 AstNode *the_range = children[0]->children[1];
1866 AstNode *left_at_zero_ast = the_range->children[0]->clone();
1867 AstNode *right_at_zero_ast = the_range->children.size() >= 2 ? the_range->children[1]->clone() : left_at_zero_ast->clone();
1868 AstNode *offset_ast = right_at_zero_ast->clone();
1869
1870 if (mem_data_range_offset)
1871 offset_ast = new AstNode(AST_SUB, offset_ast, mkconst_int(mem_data_range_offset, true));
1872
1873 while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
1874 while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
1875 if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
1876 log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
1877 int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
1878
1879 assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
1880 new AstNode(AST_SHIFT_LEFT, children[1]->clone(), offset_ast->clone()));
1881 assign_data->children[0]->str = id_data;
1882 assign_data->children[0]->was_checked = true;
1883
1884 if (current_always->type != AST_INITIAL) {
1885 for (int i = 0; i < mem_width; i++)
1886 set_bits_en[i] = i < width ? RTLIL::State::S1 : RTLIL::State::S0;
1887 assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
1888 new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone()));
1889 assign_en->children[0]->str = id_en;
1890 assign_en->children[0]->was_checked = true;
1891 }
1892
1893 delete left_at_zero_ast;
1894 delete right_at_zero_ast;
1895 delete offset_ast;
1896 }
1897 }
1898 else
1899 {
1900 assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone());
1901 assign_data->children[0]->str = id_data;
1902 assign_data->children[0]->was_checked = true;
1903
1904 if (current_always->type != AST_INITIAL) {
1905 assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
1906 assign_en->children[0]->str = id_en;
1907 assign_en->children[0]->was_checked = true;
1908 }
1909 }
1910
1911 newNode = new AstNode(AST_BLOCK);
1912 newNode->children.push_back(assign_addr);
1913 newNode->children.push_back(assign_data);
1914 if (current_always->type != AST_INITIAL)
1915 newNode->children.push_back(assign_en);
1916
1917 AstNode *wrnode = new AstNode(current_always->type == AST_INITIAL ? AST_MEMINIT : AST_MEMWR);
1918 wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
1919 wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
1920 if (current_always->type != AST_INITIAL)
1921 wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
1922 else
1923 wrnode->children.push_back(AstNode::mkconst_int(1, false));
1924 wrnode->str = children[0]->str;
1925 wrnode->id2ast = children[0]->id2ast;
1926 wrnode->children[0]->str = id_addr;
1927 wrnode->children[1]->str = id_data;
1928 if (current_always->type != AST_INITIAL)
1929 wrnode->children[2]->str = id_en;
1930 current_ast_mod->children.push_back(wrnode);
1931
1932 goto apply_newNode;
1933 }
1934
1935 // replace function and task calls with the code from the function or task
1936 if ((type == AST_FCALL || type == AST_TCALL) && !str.empty())
1937 {
1938 if (type == AST_FCALL)
1939 {
1940 if (str == "\\$initstate")
1941 {
1942 int myidx = autoidx++;
1943
1944 AstNode *wire = new AstNode(AST_WIRE);
1945 wire->str = stringf("$initstate$%d_wire", myidx);
1946 current_ast_mod->children.push_back(wire);
1947 while (wire->simplify(true, false, false, 1, -1, false, false)) { }
1948
1949 AstNode *cell = new AstNode(AST_CELL, new AstNode(AST_CELLTYPE), new AstNode(AST_ARGUMENT, new AstNode(AST_IDENTIFIER)));
1950 cell->str = stringf("$initstate$%d", myidx);
1951 cell->children[0]->str = "$initstate";
1952 cell->children[1]->str = "\\Y";
1953 cell->children[1]->children[0]->str = wire->str;
1954 cell->children[1]->children[0]->id2ast = wire;
1955 current_ast_mod->children.push_back(cell);
1956 while (cell->simplify(true, false, false, 1, -1, false, false)) { }
1957
1958 newNode = new AstNode(AST_IDENTIFIER);
1959 newNode->str = wire->str;
1960 newNode->id2ast = wire;
1961 goto apply_newNode;
1962 }
1963
1964 if (str == "\\$past")
1965 {
1966 if (width_hint < 0)
1967 goto replace_fcall_later;
1968
1969 int num_steps = 1;
1970
1971 if (GetSize(children) != 1 && GetSize(children) != 2)
1972 log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n",
1973 RTLIL::unescape_id(str).c_str(), int(children.size()));
1974
1975 if (!current_always_clocked)
1976 log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n",
1977 RTLIL::unescape_id(str).c_str());
1978
1979 if (GetSize(children) == 2)
1980 {
1981 AstNode *buf = children[1]->clone();
1982 while (buf->simplify(true, false, false, stage, -1, false, false)) { }
1983 if (buf->type != AST_CONSTANT)
1984 log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str());
1985
1986 num_steps = buf->asInt(true);
1987 delete buf;
1988 }
1989
1990 AstNode *block = nullptr;
1991
1992 for (auto child : current_always->children)
1993 if (child->type == AST_BLOCK)
1994 block = child;
1995
1996 log_assert(block != nullptr);
1997
1998 if (num_steps == 0) {
1999 newNode = children[0]->clone();
2000 goto apply_newNode;
2001 }
2002
2003 int myidx = autoidx++;
2004 AstNode *outreg = nullptr;
2005
2006 for (int i = 0; i < num_steps; i++)
2007 {
2008 AstNode *reg = new AstNode(AST_WIRE, new AstNode(AST_RANGE,
2009 mkconst_int(width_hint-1, true), mkconst_int(0, true)));
2010
2011 reg->str = stringf("$past$%s:%d$%d$%d", filename.c_str(), linenum, myidx, i);
2012 reg->is_reg = true;
2013
2014 current_ast_mod->children.push_back(reg);
2015
2016 while (reg->simplify(true, false, false, 1, -1, false, false)) { }
2017
2018 AstNode *regid = new AstNode(AST_IDENTIFIER);
2019 regid->str = reg->str;
2020 regid->id2ast = reg;
2021 regid->was_checked = true;
2022
2023 AstNode *rhs = nullptr;
2024
2025 if (outreg == nullptr) {
2026 rhs = children.at(0)->clone();
2027 } else {
2028 rhs = new AstNode(AST_IDENTIFIER);
2029 rhs->str = outreg->str;
2030 rhs->id2ast = outreg;
2031 }
2032
2033 block->children.push_back(new AstNode(AST_ASSIGN_LE, regid, rhs));
2034 outreg = reg;
2035 }
2036
2037 newNode = new AstNode(AST_IDENTIFIER);
2038 newNode->str = outreg->str;
2039 newNode->id2ast = outreg;
2040 goto apply_newNode;
2041 }
2042
2043 if (str == "\\$stable" || str == "\\$rose" || str == "\\$fell" || str == "\\$changed")
2044 {
2045 if (GetSize(children) != 1)
2046 log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
2047 RTLIL::unescape_id(str).c_str(), int(children.size()));
2048
2049 if (!current_always_clocked)
2050 log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n",
2051 RTLIL::unescape_id(str).c_str());
2052
2053 AstNode *present = children.at(0)->clone();
2054 AstNode *past = clone();
2055 past->str = "\\$past";
2056
2057 if (str == "\\$stable")
2058 newNode = new AstNode(AST_EQ, past, present);
2059
2060 else if (str == "\\$changed")
2061 newNode = new AstNode(AST_NE, past, present);
2062
2063 else if (str == "\\$rose")
2064 newNode = new AstNode(AST_LOGIC_AND,
2065 new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, past, mkconst_int(1,false))),
2066 new AstNode(AST_BIT_AND, present, mkconst_int(1,false)));
2067
2068 else if (str == "\\$fell")
2069 newNode = new AstNode(AST_LOGIC_AND,
2070 new AstNode(AST_BIT_AND, past, mkconst_int(1,false)),
2071 new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, present, mkconst_int(1,false))));
2072
2073 else
2074 log_abort();
2075
2076 goto apply_newNode;
2077 }
2078
2079 // $anyconst and $anyseq are mapped in AstNode::genRTLIL()
2080 if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq") {
2081 recursion_counter--;
2082 return false;
2083 }
2084
2085 if (str == "\\$clog2")
2086 {
2087 if (children.size() != 1)
2088 log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
2089 RTLIL::unescape_id(str).c_str(), int(children.size()));
2090
2091 AstNode *buf = children[0]->clone();
2092 while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2093 if (buf->type != AST_CONSTANT)
2094 log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str());
2095
2096 RTLIL::Const arg_value = buf->bitsAsConst();
2097 if (arg_value.as_bool())
2098 arg_value = const_sub(arg_value, 1, false, false, GetSize(arg_value));
2099 delete buf;
2100
2101 uint32_t result = 0;
2102 for (size_t i = 0; i < arg_value.bits.size(); i++)
2103 if (arg_value.bits.at(i) == RTLIL::State::S1)
2104 result = i + 1;
2105
2106 newNode = mkconst_int(result, true);
2107 goto apply_newNode;
2108 }
2109
2110 if (str == "\\$size" || str == "\\$bits")
2111 {
2112 if (str == "\\$bits" && children.size() != 1)
2113 log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
2114 RTLIL::unescape_id(str).c_str(), int(children.size()));
2115
2116 if (str == "\\$size" && children.size() != 1 && children.size() != 2)
2117 log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n",
2118 RTLIL::unescape_id(str).c_str(), int(children.size()));
2119
2120 int dim = 1;
2121 if (str == "\\$size" && children.size() == 2) {
2122 AstNode *buf = children[1]->clone();
2123 // Evaluate constant expression
2124 while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2125 dim = buf->asInt(false);
2126 delete buf;
2127 }
2128 AstNode *buf = children[0]->clone();
2129 int mem_depth = 1;
2130 AstNode *id_ast = NULL;
2131
2132 // Is this needed?
2133 //while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2134 buf->detectSignWidth(width_hint, sign_hint);
2135
2136 if (buf->type == AST_IDENTIFIER) {
2137 id_ast = buf->id2ast;
2138 if (id_ast == NULL && current_scope.count(buf->str))
2139 id_ast = current_scope.at(buf->str);
2140 if (!id_ast)
2141 log_file_error(filename, linenum, "Failed to resolve identifier %s for width detection!\n", buf->str.c_str());
2142 if (id_ast->type == AST_MEMORY) {
2143 // We got here only if the argument is a memory
2144 // Otherwise $size() and $bits() return the expression width
2145 AstNode *mem_range = id_ast->children[1];
2146 if (str == "\\$bits") {
2147 if (mem_range->type == AST_RANGE) {
2148 if (!mem_range->range_valid)
2149 log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", buf->str.c_str());
2150 mem_depth = mem_range->range_left - mem_range->range_right + 1;
2151 } else
2152 log_file_error(filename, linenum, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str());
2153 } else {
2154 // $size()
2155 if (mem_range->type == AST_RANGE) {
2156 if (!mem_range->range_valid)
2157 log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", buf->str.c_str());
2158 int dims;
2159 if (id_ast->multirange_dimensions.empty())
2160 dims = 1;
2161 else
2162 dims = GetSize(id_ast->multirange_dimensions)/2;
2163 if (dim == 1)
2164 width_hint = (dims > 1) ? id_ast->multirange_dimensions[1] : (mem_range->range_left - mem_range->range_right + 1);
2165 else if (dim <= dims) {
2166 width_hint = id_ast->multirange_dimensions[2*dim-1];
2167 } else if ((dim > dims+1) || (dim < 0))
2168 log_file_error(filename, linenum, "Dimension %d out of range in `%s', as it only has dimensions 1..%d!\n", dim, buf->str.c_str(), dims+1);
2169 } else
2170 log_file_error(filename, linenum, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str());
2171 }
2172 }
2173 }
2174 delete buf;
2175
2176 newNode = mkconst_int(width_hint * mem_depth, false);
2177 goto apply_newNode;
2178 }
2179
2180 if (str == "\\$ln" || str == "\\$log10" || str == "\\$exp" || str == "\\$sqrt" || str == "\\$pow" ||
2181 str == "\\$floor" || str == "\\$ceil" || str == "\\$sin" || str == "\\$cos" || str == "\\$tan" ||
2182 str == "\\$asin" || str == "\\$acos" || str == "\\$atan" || str == "\\$atan2" || str == "\\$hypot" ||
2183 str == "\\$sinh" || str == "\\$cosh" || str == "\\$tanh" || str == "\\$asinh" || str == "\\$acosh" || str == "\\$atanh" ||
2184 str == "\\$rtoi" || str == "\\$itor")
2185 {
2186 bool func_with_two_arguments = str == "\\$pow" || str == "\\$atan2" || str == "\\$hypot";
2187 double x = 0, y = 0;
2188
2189 if (func_with_two_arguments) {
2190 if (children.size() != 2)
2191 log_file_error(filename, linenum, "System function %s got %d arguments, expected 2.\n",
2192 RTLIL::unescape_id(str).c_str(), int(children.size()));
2193 } else {
2194 if (children.size() != 1)
2195 log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
2196 RTLIL::unescape_id(str).c_str(), int(children.size()));
2197 }
2198
2199 if (children.size() >= 1) {
2200 while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2201 if (!children[0]->isConst())
2202 log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n",
2203 RTLIL::unescape_id(str).c_str());
2204 int child_width_hint = width_hint;
2205 bool child_sign_hint = sign_hint;
2206 children[0]->detectSignWidth(child_width_hint, child_sign_hint);
2207 x = children[0]->asReal(child_sign_hint);
2208 }
2209
2210 if (children.size() >= 2) {
2211 while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2212 if (!children[1]->isConst())
2213 log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n",
2214 RTLIL::unescape_id(str).c_str());
2215 int child_width_hint = width_hint;
2216 bool child_sign_hint = sign_hint;
2217 children[1]->detectSignWidth(child_width_hint, child_sign_hint);
2218 y = children[1]->asReal(child_sign_hint);
2219 }
2220
2221 if (str == "\\$rtoi") {
2222 newNode = AstNode::mkconst_int(x, true);
2223 } else {
2224 newNode = new AstNode(AST_REALVALUE);
2225 if (str == "\\$ln") newNode->realvalue = ::log(x);
2226 else if (str == "\\$log10") newNode->realvalue = ::log10(x);
2227 else if (str == "\\$exp") newNode->realvalue = ::exp(x);
2228 else if (str == "\\$sqrt") newNode->realvalue = ::sqrt(x);
2229 else if (str == "\\$pow") newNode->realvalue = ::pow(x, y);
2230 else if (str == "\\$floor") newNode->realvalue = ::floor(x);
2231 else if (str == "\\$ceil") newNode->realvalue = ::ceil(x);
2232 else if (str == "\\$sin") newNode->realvalue = ::sin(x);
2233 else if (str == "\\$cos") newNode->realvalue = ::cos(x);
2234 else if (str == "\\$tan") newNode->realvalue = ::tan(x);
2235 else if (str == "\\$asin") newNode->realvalue = ::asin(x);
2236 else if (str == "\\$acos") newNode->realvalue = ::acos(x);
2237 else if (str == "\\$atan") newNode->realvalue = ::atan(x);
2238 else if (str == "\\$atan2") newNode->realvalue = ::atan2(x, y);
2239 else if (str == "\\$hypot") newNode->realvalue = ::hypot(x, y);
2240 else if (str == "\\$sinh") newNode->realvalue = ::sinh(x);
2241 else if (str == "\\$cosh") newNode->realvalue = ::cosh(x);
2242 else if (str == "\\$tanh") newNode->realvalue = ::tanh(x);
2243 else if (str == "\\$asinh") newNode->realvalue = ::asinh(x);
2244 else if (str == "\\$acosh") newNode->realvalue = ::acosh(x);
2245 else if (str == "\\$atanh") newNode->realvalue = ::atanh(x);
2246 else if (str == "\\$itor") newNode->realvalue = x;
2247 else log_abort();
2248 }
2249 goto apply_newNode;
2250 }
2251
2252 if (str == "\\$sformatf") {
2253 AstNode *node_string = children[0];
2254 while (node_string->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2255 if (node_string->type != AST_CONSTANT)
2256 log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str());
2257 std::string sformat = node_string->bitsAsConst().decode_string();
2258 std::string sout = process_format_str(sformat, 1, stage, width_hint, sign_hint);
2259 newNode = AstNode::mkconst_str(sout);
2260 goto apply_newNode;
2261 }
2262
2263 if (current_scope.count(str) != 0 && current_scope[str]->type == AST_DPI_FUNCTION)
2264 {
2265 AstNode *dpi_decl = current_scope[str];
2266
2267 std::string rtype, fname;
2268 std::vector<std::string> argtypes;
2269 std::vector<AstNode*> args;
2270
2271 rtype = RTLIL::unescape_id(dpi_decl->children.at(0)->str);
2272 fname = RTLIL::unescape_id(dpi_decl->children.at(1)->str);
2273
2274 for (int i = 2; i < GetSize(dpi_decl->children); i++)
2275 {
2276 if (i-2 >= GetSize(children))
2277 log_file_error(filename, linenum, "Insufficient number of arguments in DPI function call.\n");
2278
2279 argtypes.push_back(RTLIL::unescape_id(dpi_decl->children.at(i)->str));
2280 args.push_back(children.at(i-2)->clone());
2281 while (args.back()->simplify(true, false, false, stage, -1, false, true)) { }
2282
2283 if (args.back()->type != AST_CONSTANT && args.back()->type != AST_REALVALUE)
2284 log_file_error(filename, linenum, "Failed to evaluate DPI function with non-constant argument.\n");
2285 }
2286
2287 newNode = dpi_call(rtype, fname, argtypes, args);
2288
2289 for (auto arg : args)
2290 delete arg;
2291
2292 goto apply_newNode;
2293 }
2294
2295 if (current_scope.count(str) == 0 || current_scope[str]->type != AST_FUNCTION)
2296 log_file_error(filename, linenum, "Can't resolve function name `%s'.\n", str.c_str());
2297 }
2298
2299 if (type == AST_TCALL)
2300 {
2301 if (str == "$finish" || str == "$stop")
2302 {
2303 if (!current_always || current_always->type != AST_INITIAL)
2304 log_file_error(filename, linenum, "System task `%s' outside initial block is unsupported.\n", str.c_str());
2305
2306 log_file_error(filename, linenum, "System task `%s' executed.\n", str.c_str());
2307 }
2308
2309 if (str == "\\$readmemh" || str == "\\$readmemb")
2310 {
2311 if (GetSize(children) < 2 || GetSize(children) > 4)
2312 log_file_error(filename, linenum, "System function %s got %d arguments, expected 2-4.\n",
2313 RTLIL::unescape_id(str).c_str(), int(children.size()));
2314
2315 AstNode *node_filename = children[0]->clone();
2316 while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2317 if (node_filename->type != AST_CONSTANT)
2318 log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str());
2319
2320 AstNode *node_memory = children[1]->clone();
2321 while (node_memory->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2322 if (node_memory->type != AST_IDENTIFIER || node_memory->id2ast == nullptr || node_memory->id2ast->type != AST_MEMORY)
2323 log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str.c_str());
2324
2325 int start_addr = -1, finish_addr = -1;
2326
2327 if (GetSize(children) > 2) {
2328 AstNode *node_addr = children[2]->clone();
2329 while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2330 if (node_addr->type != AST_CONSTANT)
2331 log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str.c_str());
2332 start_addr = int(node_addr->asInt(false));
2333 }
2334
2335 if (GetSize(children) > 3) {
2336 AstNode *node_addr = children[3]->clone();
2337 while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2338 if (node_addr->type != AST_CONSTANT)
2339 log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str.c_str());
2340 finish_addr = int(node_addr->asInt(false));
2341 }
2342
2343 bool unconditional_init = false;
2344 if (current_always->type == AST_INITIAL) {
2345 pool<AstNode*> queue;
2346 log_assert(current_always->children[0]->type == AST_BLOCK);
2347 queue.insert(current_always->children[0]);
2348 while (!unconditional_init && !queue.empty()) {
2349 pool<AstNode*> next_queue;
2350 for (auto n : queue)
2351 for (auto c : n->children) {
2352 if (c == this)
2353 unconditional_init = true;
2354 next_queue.insert(c);
2355 }
2356 next_queue.swap(queue);
2357 }
2358 }
2359
2360 newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init);
2361 delete node_filename;
2362 delete node_memory;
2363 goto apply_newNode;
2364 }
2365
2366 if (current_scope.count(str) == 0 || current_scope[str]->type != AST_TASK)
2367 log_file_error(filename, linenum, "Can't resolve task name `%s'.\n", str.c_str());
2368 }
2369
2370 AstNode *decl = current_scope[str];
2371
2372 std::stringstream sstr;
2373 sstr << "$func$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++) << "$";
2374 std::string prefix = sstr.str();
2375
2376 bool recommend_const_eval = false;
2377 bool require_const_eval = in_param ? false : has_const_only_constructs(recommend_const_eval);
2378 if ((in_param || recommend_const_eval || require_const_eval) && !decl->attributes.count("\\via_celltype"))
2379 {
2380 bool all_args_const = true;
2381 for (auto child : children) {
2382 while (child->simplify(true, false, false, 1, -1, false, true)) { }
2383 if (child->type != AST_CONSTANT)
2384 all_args_const = false;
2385 }
2386
2387 if (all_args_const) {
2388 AstNode *func_workspace = current_scope[str]->clone();
2389 newNode = func_workspace->eval_const_function(this);
2390 delete func_workspace;
2391 goto apply_newNode;
2392 }
2393
2394 if (in_param)
2395 log_file_error(filename, linenum, "Non-constant function call in constant expression.\n");
2396 if (require_const_eval)
2397 log_file_error(filename, linenum, "Function %s can only be called with constant arguments.\n", str.c_str());
2398 }
2399
2400 size_t arg_count = 0;
2401 std::map<std::string, std::string> replace_rules;
2402 vector<AstNode*> added_mod_children;
2403 dict<std::string, AstNode*> wire_cache;
2404 vector<AstNode*> new_stmts;
2405 vector<AstNode*> output_assignments;
2406
2407 if (current_block == NULL)
2408 {
2409 log_assert(type == AST_FCALL);
2410
2411 AstNode *wire = NULL;
2412 for (auto child : decl->children)
2413 if (child->type == AST_WIRE && child->str == str)
2414 wire = child->clone();
2415 log_assert(wire != NULL);
2416
2417 wire->str = prefix + str;
2418 wire->port_id = 0;
2419 wire->is_input = false;
2420 wire->is_output = false;
2421
2422 current_ast_mod->children.push_back(wire);
2423 while (wire->simplify(true, false, false, 1, -1, false, false)) { }
2424
2425 AstNode *lvalue = new AstNode(AST_IDENTIFIER);
2426 lvalue->str = wire->str;
2427
2428 AstNode *always = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK,
2429 new AstNode(AST_ASSIGN_EQ, lvalue, clone())));
2430 always->children[0]->children[0]->was_checked = true;
2431
2432 current_ast_mod->children.push_back(always);
2433
2434 goto replace_fcall_with_id;
2435 }
2436
2437 if (decl->attributes.count("\\via_celltype"))
2438 {
2439 std::string celltype = decl->attributes.at("\\via_celltype")->asAttrConst().decode_string();
2440 std::string outport = str;
2441
2442 if (celltype.find(' ') != std::string::npos) {
2443 int pos = celltype.find(' ');
2444 outport = RTLIL::escape_id(celltype.substr(pos+1));
2445 celltype = RTLIL::escape_id(celltype.substr(0, pos));
2446 } else
2447 celltype = RTLIL::escape_id(celltype);
2448
2449 AstNode *cell = new AstNode(AST_CELL, new AstNode(AST_CELLTYPE));
2450 cell->str = prefix.substr(0, GetSize(prefix)-1);
2451 cell->children[0]->str = celltype;
2452
2453 for (auto attr : decl->attributes)
2454 if (attr.first.str().rfind("\\via_celltype_defparam_", 0) == 0)
2455 {
2456 AstNode *cell_arg = new AstNode(AST_PARASET, attr.second->clone());
2457 cell_arg->str = RTLIL::escape_id(attr.first.substr(strlen("\\via_celltype_defparam_")));
2458 cell->children.push_back(cell_arg);
2459 }
2460
2461 for (auto child : decl->children)
2462 if (child->type == AST_WIRE && (child->is_input || child->is_output || (type == AST_FCALL && child->str == str)))
2463 {
2464 AstNode *wire = child->clone();
2465 wire->str = prefix + wire->str;
2466 wire->port_id = 0;
2467 wire->is_input = false;
2468 wire->is_output = false;
2469 current_ast_mod->children.push_back(wire);
2470 while (wire->simplify(true, false, false, 1, -1, false, false)) { }
2471
2472 AstNode *wire_id = new AstNode(AST_IDENTIFIER);
2473 wire_id->str = wire->str;
2474
2475 if ((child->is_input || child->is_output) && arg_count < children.size())
2476 {
2477 AstNode *arg = children[arg_count++]->clone();
2478 AstNode *assign = child->is_input ?
2479 new AstNode(AST_ASSIGN_EQ, wire_id->clone(), arg) :
2480 new AstNode(AST_ASSIGN_EQ, arg, wire_id->clone());
2481 assign->children[0]->was_checked = true;
2482
2483 for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
2484 if (*it != current_block_child)
2485 continue;
2486 current_block->children.insert(it, assign);
2487 break;
2488 }
2489 }
2490
2491 AstNode *cell_arg = new AstNode(AST_ARGUMENT, wire_id);
2492 cell_arg->str = child->str == str ? outport : child->str;
2493 cell->children.push_back(cell_arg);
2494 }
2495
2496 current_ast_mod->children.push_back(cell);
2497 goto replace_fcall_with_id;
2498 }
2499
2500 for (auto child : decl->children)
2501 if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM)
2502 {
2503 AstNode *wire = nullptr;
2504
2505 if (wire_cache.count(child->str))
2506 {
2507 wire = wire_cache.at(child->str);
2508 if (wire->children.empty()) {
2509 for (auto c : child->children)
2510 wire->children.push_back(c->clone());
2511 } else if (!child->children.empty()) {
2512 while (child->simplify(true, false, false, stage, -1, false, false)) { }
2513 if (GetSize(child->children) == GetSize(wire->children)) {
2514 for (int i = 0; i < GetSize(child->children); i++)
2515 if (*child->children.at(i) != *wire->children.at(i))
2516 goto tcall_incompatible_wires;
2517 } else {
2518 tcall_incompatible_wires:
2519 log_file_error(filename, linenum, "Incompatible re-declaration of wire %s.\n", child->str.c_str());
2520 }
2521 }
2522 }
2523 else
2524 {
2525 wire = child->clone();
2526 wire->str = prefix + wire->str;
2527 wire->port_id = 0;
2528 wire->is_input = false;
2529 wire->is_output = false;
2530 wire->is_reg = true;
2531 wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
2532 wire_cache[child->str] = wire;
2533
2534 current_ast_mod->children.push_back(wire);
2535 added_mod_children.push_back(wire);
2536 }
2537
2538 if (child->type == AST_WIRE)
2539 while (wire->simplify(true, false, false, 1, -1, false, false)) { }
2540
2541 replace_rules[child->str] = wire->str;
2542 current_scope[wire->str] = wire;
2543
2544 if ((child->is_input || child->is_output) && arg_count < children.size())
2545 {
2546 AstNode *arg = children[arg_count++]->clone();
2547 AstNode *wire_id = new AstNode(AST_IDENTIFIER);
2548 wire_id->str = wire->str;
2549 AstNode *assign = child->is_input ?
2550 new AstNode(AST_ASSIGN_EQ, wire_id, arg) :
2551 new AstNode(AST_ASSIGN_EQ, arg, wire_id);
2552 assign->children[0]->was_checked = true;
2553 if (child->is_input)
2554 new_stmts.push_back(assign);
2555 else
2556 output_assignments.push_back(assign);
2557 }
2558 }
2559
2560 for (auto child : added_mod_children) {
2561 child->replace_ids(prefix, replace_rules);
2562 while (child->simplify(true, false, false, 1, -1, false, false)) { }
2563 }
2564
2565 for (auto child : decl->children)
2566 if (child->type != AST_WIRE && child->type != AST_MEMORY && child->type != AST_PARAMETER && child->type != AST_LOCALPARAM)
2567 {
2568 AstNode *stmt = child->clone();
2569 stmt->replace_ids(prefix, replace_rules);
2570 new_stmts.push_back(stmt);
2571 }
2572
2573 new_stmts.insert(new_stmts.end(), output_assignments.begin(), output_assignments.end());
2574
2575 for (auto it = current_block->children.begin(); ; it++) {
2576 log_assert(it != current_block->children.end());
2577 if (*it == current_block_child) {
2578 current_block->children.insert(it, new_stmts.begin(), new_stmts.end());
2579 break;
2580 }
2581 }
2582
2583 replace_fcall_with_id:
2584 if (type == AST_FCALL) {
2585 delete_children();
2586 type = AST_IDENTIFIER;
2587 str = prefix + str;
2588 }
2589 if (type == AST_TCALL)
2590 str = "";
2591 did_something = true;
2592 }
2593
2594 replace_fcall_later:;
2595
2596 // perform const folding when activated
2597 if (const_fold)
2598 {
2599 bool string_op;
2600 std::vector<RTLIL::State> tmp_bits;
2601 RTLIL::Const (*const_func)(const RTLIL::Const&, const RTLIL::Const&, bool, bool, int);
2602 RTLIL::Const dummy_arg;
2603
2604 switch (type)
2605 {
2606 case AST_IDENTIFIER:
2607 if (current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM)) {
2608 if (current_scope[str]->children[0]->type == AST_CONSTANT) {
2609 if (children.size() != 0 && children[0]->type == AST_RANGE && children[0]->range_valid) {
2610 std::vector<RTLIL::State> data;
2611 bool param_upto = current_scope[str]->range_valid && current_scope[str]->range_swapped;
2612 int param_offset = current_scope[str]->range_valid ? current_scope[str]->range_right : 0;
2613 int param_width = current_scope[str]->range_valid ? current_scope[str]->range_left - current_scope[str]->range_right + 1 :
2614 GetSize(current_scope[str]->children[0]->bits);
2615 int tmp_range_left = children[0]->range_left, tmp_range_right = children[0]->range_right;
2616 if (param_upto) {
2617 tmp_range_left = (param_width + 2*param_offset) - children[0]->range_right - 1;
2618 tmp_range_right = (param_width + 2*param_offset) - children[0]->range_left - 1;
2619 }
2620 for (int i = tmp_range_right; i <= tmp_range_left; i++) {
2621 int index = i - param_offset;
2622 if (0 <= index && index < param_width)
2623 data.push_back(current_scope[str]->children[0]->bits[index]);
2624 else
2625 data.push_back(RTLIL::State::Sx);
2626 }
2627 newNode = mkconst_bits(data, false);
2628 } else
2629 if (children.size() == 0)
2630 newNode = current_scope[str]->children[0]->clone();
2631 } else
2632 if (current_scope[str]->children[0]->isConst())
2633 newNode = current_scope[str]->children[0]->clone();
2634 }
2635 else if (at_zero && current_scope.count(str) > 0 && (current_scope[str]->type == AST_WIRE || current_scope[str]->type == AST_AUTOWIRE)) {
2636 newNode = mkconst_int(0, sign_hint, width_hint);
2637 }
2638 break;
2639 case AST_BIT_NOT:
2640 if (children[0]->type == AST_CONSTANT) {
2641 RTLIL::Const y = RTLIL::const_not(children[0]->bitsAsConst(width_hint, sign_hint), dummy_arg, sign_hint, false, width_hint);
2642 newNode = mkconst_bits(y.bits, sign_hint);
2643 }
2644 break;
2645 case AST_TO_SIGNED:
2646 case AST_TO_UNSIGNED:
2647 if (children[0]->type == AST_CONSTANT) {
2648 RTLIL::Const y = children[0]->bitsAsConst(width_hint, sign_hint);
2649 newNode = mkconst_bits(y.bits, type == AST_TO_SIGNED);
2650 }
2651 break;
2652 if (0) { case AST_BIT_AND: const_func = RTLIL::const_and; }
2653 if (0) { case AST_BIT_OR: const_func = RTLIL::const_or; }
2654 if (0) { case AST_BIT_XOR: const_func = RTLIL::const_xor; }
2655 if (0) { case AST_BIT_XNOR: const_func = RTLIL::const_xnor; }
2656 if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
2657 RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
2658 children[1]->bitsAsConst(width_hint, sign_hint), sign_hint, sign_hint, width_hint);
2659 newNode = mkconst_bits(y.bits, sign_hint);
2660 }
2661 break;
2662 if (0) { case AST_REDUCE_AND: const_func = RTLIL::const_reduce_and; }
2663 if (0) { case AST_REDUCE_OR: const_func = RTLIL::const_reduce_or; }
2664 if (0) { case AST_REDUCE_XOR: const_func = RTLIL::const_reduce_xor; }
2665 if (0) { case AST_REDUCE_XNOR: const_func = RTLIL::const_reduce_xnor; }
2666 if (0) { case AST_REDUCE_BOOL: const_func = RTLIL::const_reduce_bool; }
2667 if (children[0]->type == AST_CONSTANT) {
2668 RTLIL::Const y = const_func(RTLIL::Const(children[0]->bits), dummy_arg, false, false, -1);
2669 newNode = mkconst_bits(y.bits, false);
2670 }
2671 break;
2672 case AST_LOGIC_NOT:
2673 if (children[0]->type == AST_CONSTANT) {
2674 RTLIL::Const y = RTLIL::const_logic_not(RTLIL::Const(children[0]->bits), dummy_arg, children[0]->is_signed, false, -1);
2675 newNode = mkconst_bits(y.bits, false);
2676 } else
2677 if (children[0]->isConst()) {
2678 newNode = mkconst_int(children[0]->asReal(sign_hint) == 0, false, 1);
2679 }
2680 break;
2681 if (0) { case AST_LOGIC_AND: const_func = RTLIL::const_logic_and; }
2682 if (0) { case AST_LOGIC_OR: const_func = RTLIL::const_logic_or; }
2683 if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
2684 RTLIL::Const y = const_func(RTLIL::Const(children[0]->bits), RTLIL::Const(children[1]->bits),
2685 children[0]->is_signed, children[1]->is_signed, -1);
2686 newNode = mkconst_bits(y.bits, false);
2687 } else
2688 if (children[0]->isConst() && children[1]->isConst()) {
2689 if (type == AST_LOGIC_AND)
2690 newNode = mkconst_int((children[0]->asReal(sign_hint) != 0) && (children[1]->asReal(sign_hint) != 0), false, 1);
2691 else
2692 newNode = mkconst_int((children[0]->asReal(sign_hint) != 0) || (children[1]->asReal(sign_hint) != 0), false, 1);
2693 }
2694 break;
2695 if (0) { case AST_SHIFT_LEFT: const_func = RTLIL::const_shl; }
2696 if (0) { case AST_SHIFT_RIGHT: const_func = RTLIL::const_shr; }
2697 if (0) { case AST_SHIFT_SLEFT: const_func = RTLIL::const_sshl; }
2698 if (0) { case AST_SHIFT_SRIGHT: const_func = RTLIL::const_sshr; }
2699 if (0) { case AST_POW: const_func = RTLIL::const_pow; }
2700 if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
2701 RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
2702 RTLIL::Const(children[1]->bits), sign_hint, type == AST_POW ? children[1]->is_signed : false, width_hint);
2703 newNode = mkconst_bits(y.bits, sign_hint);
2704 } else
2705 if (type == AST_POW && children[0]->isConst() && children[1]->isConst()) {
2706 newNode = new AstNode(AST_REALVALUE);
2707 newNode->realvalue = pow(children[0]->asReal(sign_hint), children[1]->asReal(sign_hint));
2708 }
2709 break;
2710 if (0) { case AST_LT: const_func = RTLIL::const_lt; }
2711 if (0) { case AST_LE: const_func = RTLIL::const_le; }
2712 if (0) { case AST_EQ: const_func = RTLIL::const_eq; }
2713 if (0) { case AST_NE: const_func = RTLIL::const_ne; }
2714 if (0) { case AST_EQX: const_func = RTLIL::const_eqx; }
2715 if (0) { case AST_NEX: const_func = RTLIL::const_nex; }
2716 if (0) { case AST_GE: const_func = RTLIL::const_ge; }
2717 if (0) { case AST_GT: const_func = RTLIL::const_gt; }
2718 if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
2719 int cmp_width = max(children[0]->bits.size(), children[1]->bits.size());
2720 bool cmp_signed = children[0]->is_signed && children[1]->is_signed;
2721 RTLIL::Const y = const_func(children[0]->bitsAsConst(cmp_width, cmp_signed),
2722 children[1]->bitsAsConst(cmp_width, cmp_signed), cmp_signed, cmp_signed, 1);
2723 newNode = mkconst_bits(y.bits, false);
2724 } else
2725 if (children[0]->isConst() && children[1]->isConst()) {
2726 bool cmp_signed = (children[0]->type == AST_REALVALUE || children[0]->is_signed) && (children[1]->type == AST_REALVALUE || children[1]->is_signed);
2727 switch (type) {
2728 case AST_LT: newNode = mkconst_int(children[0]->asReal(cmp_signed) < children[1]->asReal(cmp_signed), false, 1); break;
2729 case AST_LE: newNode = mkconst_int(children[0]->asReal(cmp_signed) <= children[1]->asReal(cmp_signed), false, 1); break;
2730 case AST_EQ: newNode = mkconst_int(children[0]->asReal(cmp_signed) == children[1]->asReal(cmp_signed), false, 1); break;
2731 case AST_NE: newNode = mkconst_int(children[0]->asReal(cmp_signed) != children[1]->asReal(cmp_signed), false, 1); break;
2732 case AST_EQX: newNode = mkconst_int(children[0]->asReal(cmp_signed) == children[1]->asReal(cmp_signed), false, 1); break;
2733 case AST_NEX: newNode = mkconst_int(children[0]->asReal(cmp_signed) != children[1]->asReal(cmp_signed), false, 1); break;
2734 case AST_GE: newNode = mkconst_int(children[0]->asReal(cmp_signed) >= children[1]->asReal(cmp_signed), false, 1); break;
2735 case AST_GT: newNode = mkconst_int(children[0]->asReal(cmp_signed) > children[1]->asReal(cmp_signed), false, 1); break;
2736 default: log_abort();
2737 }
2738 }
2739 break;
2740 if (0) { case AST_ADD: const_func = RTLIL::const_add; }
2741 if (0) { case AST_SUB: const_func = RTLIL::const_sub; }
2742 if (0) { case AST_MUL: const_func = RTLIL::const_mul; }
2743 if (0) { case AST_DIV: const_func = RTLIL::const_div; }
2744 if (0) { case AST_MOD: const_func = RTLIL::const_mod; }
2745 if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
2746 RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
2747 children[1]->bitsAsConst(width_hint, sign_hint), sign_hint, sign_hint, width_hint);
2748 newNode = mkconst_bits(y.bits, sign_hint);
2749 } else
2750 if (children[0]->isConst() && children[1]->isConst()) {
2751 newNode = new AstNode(AST_REALVALUE);
2752 switch (type) {
2753 case AST_ADD: newNode->realvalue = children[0]->asReal(sign_hint) + children[1]->asReal(sign_hint); break;
2754 case AST_SUB: newNode->realvalue = children[0]->asReal(sign_hint) - children[1]->asReal(sign_hint); break;
2755 case AST_MUL: newNode->realvalue = children[0]->asReal(sign_hint) * children[1]->asReal(sign_hint); break;
2756 case AST_DIV: newNode->realvalue = children[0]->asReal(sign_hint) / children[1]->asReal(sign_hint); break;
2757 case AST_MOD: newNode->realvalue = fmod(children[0]->asReal(sign_hint), children[1]->asReal(sign_hint)); break;
2758 default: log_abort();
2759 }
2760 }
2761 break;
2762 if (0) { case AST_POS: const_func = RTLIL::const_pos; }
2763 if (0) { case AST_NEG: const_func = RTLIL::const_neg; }
2764 if (children[0]->type == AST_CONSTANT) {
2765 RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint), dummy_arg, sign_hint, false, width_hint);
2766 newNode = mkconst_bits(y.bits, sign_hint);
2767 } else
2768 if (children[0]->isConst()) {
2769 newNode = new AstNode(AST_REALVALUE);
2770 if (type == AST_POS)
2771 newNode->realvalue = +children[0]->asReal(sign_hint);
2772 else
2773 newNode->realvalue = -children[0]->asReal(sign_hint);
2774 }
2775 break;
2776 case AST_TERNARY:
2777 if (children[0]->isConst())
2778 {
2779 bool found_sure_true = false;
2780 bool found_maybe_true = false;
2781
2782 if (children[0]->type == AST_CONSTANT)
2783 for (auto &bit : children[0]->bits) {
2784 if (bit == RTLIL::State::S1)
2785 found_sure_true = true;
2786 if (bit > RTLIL::State::S1)
2787 found_maybe_true = true;
2788 }
2789 else
2790 found_sure_true = children[0]->asReal(sign_hint) != 0;
2791
2792 AstNode *choice = NULL, *not_choice = NULL;
2793 if (found_sure_true)
2794 choice = children[1], not_choice = children[2];
2795 else if (!found_maybe_true)
2796 choice = children[2], not_choice = children[1];
2797
2798 if (choice != NULL) {
2799 if (choice->type == AST_CONSTANT) {
2800 int other_width_hint = width_hint;
2801 bool other_sign_hint = sign_hint, other_real = false;
2802 not_choice->detectSignWidth(other_width_hint, other_sign_hint, &other_real);
2803 if (other_real) {
2804 newNode = new AstNode(AST_REALVALUE);
2805 choice->detectSignWidth(width_hint, sign_hint);
2806 newNode->realvalue = choice->asReal(sign_hint);
2807 } else {
2808 RTLIL::Const y = choice->bitsAsConst(width_hint, sign_hint);
2809 if (choice->is_string && y.bits.size() % 8 == 0 && sign_hint == false)
2810 newNode = mkconst_str(y.bits);
2811 else
2812 newNode = mkconst_bits(y.bits, sign_hint);
2813 }
2814 } else
2815 if (choice->isConst()) {
2816 newNode = choice->clone();
2817 }
2818 } else if (children[1]->type == AST_CONSTANT && children[2]->type == AST_CONSTANT) {
2819 RTLIL::Const a = children[1]->bitsAsConst(width_hint, sign_hint);
2820 RTLIL::Const b = children[2]->bitsAsConst(width_hint, sign_hint);
2821 log_assert(a.bits.size() == b.bits.size());
2822 for (size_t i = 0; i < a.bits.size(); i++)
2823 if (a.bits[i] != b.bits[i])
2824 a.bits[i] = RTLIL::State::Sx;
2825 newNode = mkconst_bits(a.bits, sign_hint);
2826 } else if (children[1]->isConst() && children[2]->isConst()) {
2827 newNode = new AstNode(AST_REALVALUE);
2828 if (children[1]->asReal(sign_hint) == children[2]->asReal(sign_hint))
2829 newNode->realvalue = children[1]->asReal(sign_hint);
2830 else
2831 // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
2832 // the data type in question should be returned if the ?: is ambiguous. The
2833 // value in Table 7-1 for the 'real' type is 0.0.
2834 newNode->realvalue = 0.0;
2835 }
2836 }
2837 break;
2838 case AST_CONCAT:
2839 string_op = !children.empty();
2840 for (auto it = children.begin(); it != children.end(); it++) {
2841 if ((*it)->type != AST_CONSTANT)
2842 goto not_const;
2843 if (!(*it)->is_string)
2844 string_op = false;
2845 tmp_bits.insert(tmp_bits.end(), (*it)->bits.begin(), (*it)->bits.end());
2846 }
2847 newNode = string_op ? mkconst_str(tmp_bits) : mkconst_bits(tmp_bits, false);
2848 break;
2849 case AST_REPLICATE:
2850 if (children.at(0)->type != AST_CONSTANT || children.at(1)->type != AST_CONSTANT)
2851 goto not_const;
2852 for (int i = 0; i < children[0]->bitsAsConst().as_int(); i++)
2853 tmp_bits.insert(tmp_bits.end(), children.at(1)->bits.begin(), children.at(1)->bits.end());
2854 newNode = children.at(1)->is_string ? mkconst_str(tmp_bits) : mkconst_bits(tmp_bits, false);
2855 break;
2856 default:
2857 not_const:
2858 break;
2859 }
2860 }
2861
2862 // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
2863 if (newNode) {
2864 apply_newNode:
2865 // fprintf(stderr, "----\n");
2866 // dumpAst(stderr, "- ");
2867 // newNode->dumpAst(stderr, "+ ");
2868 log_assert(newNode != NULL);
2869 newNode->filename = filename;
2870 newNode->linenum = linenum;
2871 newNode->cloneInto(this);
2872 delete newNode;
2873 did_something = true;
2874 }
2875
2876 if (!did_something)
2877 basic_prep = true;
2878
2879 recursion_counter--;
2880 return did_something;
2881 }
2882
2883 static void replace_result_wire_name_in_function(AstNode *node, std::string &from, std::string &to)
2884 {
2885 for (auto &it : node->children)
2886 replace_result_wire_name_in_function(it, from, to);
2887 if (node->str == from)
2888 node->str = to;
2889 }
2890
2891 // replace a readmem[bh] TCALL ast node with a block of memory assignments
2892 AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init)
2893 {
2894 int mem_width, mem_size, addr_bits;
2895 memory->meminfo(mem_width, mem_size, addr_bits);
2896
2897 AstNode *block = new AstNode(AST_BLOCK);
2898
2899 AstNode *meminit = nullptr;
2900 int next_meminit_cursor=0;
2901 vector<State> meminit_bits;
2902 int meminit_size=0;
2903
2904 std::ifstream f;
2905 f.open(mem_filename.c_str());
2906 if (f.fail()) {
2907 #ifdef _WIN32
2908 char slash = '\\';
2909 #else
2910 char slash = '/';
2911 #endif
2912 std::string path = filename.substr(0, filename.find_last_of(slash)+1);
2913 f.open(path + mem_filename.c_str());
2914 yosys_input_files.insert(path + mem_filename);
2915 } else {
2916 yosys_input_files.insert(mem_filename);
2917 }
2918 if (f.fail() || GetSize(mem_filename) == 0)
2919 log_file_error(filename, linenum, "Can not open file `%s` for %s.\n", mem_filename.c_str(), str.c_str());
2920
2921 log_assert(GetSize(memory->children) == 2 && memory->children[1]->type == AST_RANGE && memory->children[1]->range_valid);
2922 int range_left = memory->children[1]->range_left, range_right = memory->children[1]->range_right;
2923 int range_min = min(range_left, range_right), range_max = max(range_left, range_right);
2924
2925 if (start_addr < 0)
2926 start_addr = range_min;
2927
2928 if (finish_addr < 0)
2929 finish_addr = range_max + 1;
2930
2931 bool in_comment = false;
2932 int increment = start_addr <= finish_addr ? +1 : -1;
2933 int cursor = start_addr;
2934
2935 while (!f.eof())
2936 {
2937 std::string line, token;
2938 std::getline(f, line);
2939
2940 for (int i = 0; i < GetSize(line); i++) {
2941 if (in_comment && line.compare(i, 2, "*/") == 0) {
2942 line[i] = ' ';
2943 line[i+1] = ' ';
2944 in_comment = false;
2945 continue;
2946 }
2947 if (!in_comment && line.compare(i, 2, "/*") == 0)
2948 in_comment = true;
2949 if (in_comment)
2950 line[i] = ' ';
2951 }
2952
2953 while (1)
2954 {
2955 token = next_token(line, " \t\r\n");
2956 if (token.empty() || token.compare(0, 2, "//") == 0)
2957 break;
2958
2959 if (token[0] == '@') {
2960 token = token.substr(1);
2961 const char *nptr = token.c_str();
2962 char *endptr;
2963 cursor = strtol(nptr, &endptr, 16);
2964 if (!*nptr || *endptr)
2965 log_file_error(filename, linenum, "Can not parse address `%s` for %s.\n", nptr, str.c_str());
2966 continue;
2967 }
2968
2969 AstNode *value = VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width, is_readmemh ? 'h' : 'b') + token);
2970
2971 if (unconditional_init)
2972 {
2973 if (meminit == nullptr || cursor != next_meminit_cursor)
2974 {
2975 if (meminit != nullptr) {
2976 meminit->children[1] = AstNode::mkconst_bits(meminit_bits, false);
2977 meminit->children[2] = AstNode::mkconst_int(meminit_size, false);
2978 }
2979
2980 meminit = new AstNode(AST_MEMINIT);
2981 meminit->children.push_back(AstNode::mkconst_int(cursor, false));
2982 meminit->children.push_back(nullptr);
2983 meminit->children.push_back(nullptr);
2984 meminit->str = memory->str;
2985 meminit->id2ast = memory;
2986 meminit_bits.clear();
2987 meminit_size = 0;
2988
2989 current_ast_mod->children.push_back(meminit);
2990 next_meminit_cursor = cursor;
2991 }
2992
2993 meminit_size++;
2994 next_meminit_cursor++;
2995 meminit_bits.insert(meminit_bits.end(), value->bits.begin(), value->bits.end());
2996 delete value;
2997 }
2998 else
2999 {
3000 block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor, false))), value));
3001 block->children.back()->children[0]->str = memory->str;
3002 block->children.back()->children[0]->id2ast = memory;
3003 block->children.back()->children[0]->was_checked = true;
3004 }
3005
3006 cursor += increment;
3007 if ((cursor == finish_addr+increment) || (increment > 0 && cursor > range_max) || (increment < 0 && cursor < range_min))
3008 break;
3009 }
3010
3011 if ((cursor == finish_addr+increment) || (increment > 0 && cursor > range_max) || (increment < 0 && cursor < range_min))
3012 break;
3013 }
3014
3015 if (meminit != nullptr) {
3016 meminit->children[1] = AstNode::mkconst_bits(meminit_bits, false);
3017 meminit->children[2] = AstNode::mkconst_int(meminit_size, false);
3018 }
3019
3020 return block;
3021 }
3022
3023 // annotate the names of all wires and other named objects in a generate block
3024 void AstNode::expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map)
3025 {
3026 if (!index_var.empty() && type == AST_IDENTIFIER && str == index_var) {
3027 if (children.empty()) {
3028 current_scope[index_var]->children[0]->cloneInto(this);
3029 } else {
3030 AstNode *p = new AstNode(AST_LOCALPARAM, current_scope[index_var]->children[0]->clone());
3031 p->str = stringf("$genval$%d", autoidx++);
3032 current_ast_mod->children.push_back(p);
3033 str = p->str;
3034 id2ast = p;
3035
3036 auto resolved = current_scope.at(index_var);
3037 if (resolved->range_valid) {
3038 p->range_left = resolved->range_left;
3039 p->range_right = resolved->range_right;
3040 p->range_swapped = resolved->range_swapped;
3041 p->range_valid = resolved->range_valid;
3042 }
3043 }
3044 }
3045
3046 if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE) && name_map.count(str) > 0)
3047 str = name_map[str];
3048
3049 std::map<std::string, std::string> backup_name_map;
3050
3051 for (size_t i = 0; i < children.size(); i++) {
3052 AstNode *child = children[i];
3053 if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM ||
3054 child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF) {
3055 if (backup_name_map.size() == 0)
3056 backup_name_map = name_map;
3057 std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
3058 size_t pos = child->str.rfind('.');
3059 if (pos == std::string::npos)
3060 pos = child->str[0] == '\\' && prefix[0] == '\\' ? 1 : 0;
3061 else
3062 pos = pos + 1;
3063 new_name = child->str.substr(0, pos) + new_name + child->str.substr(pos);
3064 if (new_name[0] != '$' && new_name[0] != '\\')
3065 new_name = prefix[0] + new_name;
3066 name_map[child->str] = new_name;
3067 if (child->type == AST_FUNCTION)
3068 replace_result_wire_name_in_function(child, child->str, new_name);
3069 else
3070 child->str = new_name;
3071 current_scope[new_name] = child;
3072 }
3073 }
3074
3075 for (size_t i = 0; i < children.size(); i++) {
3076 AstNode *child = children[i];
3077 // AST_PREFIX member names should not be prefixed; a nested AST_PREFIX
3078 // still needs to recursed-into
3079 if (type == AST_PREFIX && i == 1 && child->type == AST_IDENTIFIER)
3080 continue;
3081 if (child->type != AST_FUNCTION && child->type != AST_TASK)
3082 child->expand_genblock(index_var, prefix, name_map);
3083 }
3084
3085
3086 if (backup_name_map.size() > 0)
3087 name_map.swap(backup_name_map);
3088 }
3089
3090 // rename stuff (used when tasks of functions are instantiated)
3091 void AstNode::replace_ids(const std::string &prefix, const std::map<std::string, std::string> &rules)
3092 {
3093 if (type == AST_BLOCK)
3094 {
3095 std::map<std::string, std::string> new_rules = rules;
3096 std::string new_prefix = prefix + str;
3097
3098 for (auto child : children)
3099 if (child->type == AST_WIRE) {
3100 new_rules[child->str] = new_prefix + child->str;
3101 child->str = new_prefix + child->str;
3102 }
3103
3104 for (auto child : children)
3105 if (child->type != AST_WIRE)
3106 child->replace_ids(new_prefix, new_rules);
3107 }
3108 else
3109 {
3110 if (type == AST_IDENTIFIER && rules.count(str) > 0)
3111 str = rules.at(str);
3112 for (auto child : children)
3113 child->replace_ids(prefix, rules);
3114 }
3115 }
3116
3117 // helper function for mem2reg_as_needed_pass1
3118 static void mark_memories_assign_lhs_complex(dict<AstNode*, pool<std::string>> &mem2reg_places,
3119 dict<AstNode*, uint32_t> &mem2reg_candidates, AstNode *that)
3120 {
3121 for (auto &child : that->children)
3122 mark_memories_assign_lhs_complex(mem2reg_places, mem2reg_candidates, child);
3123
3124 if (that->type == AST_IDENTIFIER && that->id2ast && that->id2ast->type == AST_MEMORY) {
3125 AstNode *mem = that->id2ast;
3126 if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_CMPLX_LHS))
3127 mem2reg_places[mem].insert(stringf("%s:%d", that->filename.c_str(), that->linenum));
3128 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CMPLX_LHS;
3129 }
3130 }
3131
3132 // find memories that should be replaced by registers
3133 void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg_places,
3134 dict<AstNode*, uint32_t> &mem2reg_candidates, dict<AstNode*, uint32_t> &proc_flags, uint32_t &flags)
3135 {
3136 uint32_t children_flags = 0;
3137 int lhs_children_counter = 0;
3138
3139 if (type == AST_TYPEDEF)
3140 return; // don't touch content of typedefs
3141
3142 if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ)
3143 {
3144 // mark all memories that are used in a complex expression on the left side of an assignment
3145 for (auto &lhs_child : children[0]->children)
3146 mark_memories_assign_lhs_complex(mem2reg_places, mem2reg_candidates, lhs_child);
3147
3148 if (children[0]->type == AST_IDENTIFIER && children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY)
3149 {
3150 AstNode *mem = children[0]->id2ast;
3151
3152 // activate mem2reg if this is assigned in an async proc
3153 if (flags & AstNode::MEM2REG_FL_ASYNC) {
3154 if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ASYNC))
3155 mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
3156 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ASYNC;
3157 }
3158
3159 // remember if this is assigned blocking (=)
3160 if (type == AST_ASSIGN_EQ) {
3161 if (!(proc_flags[mem] & AstNode::MEM2REG_FL_EQ1))
3162 mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
3163 proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1;
3164 }
3165
3166 // for proper (non-init) writes: remember if this is a constant index or not
3167 if ((flags & MEM2REG_FL_INIT) == 0) {
3168 if (children[0]->children.size() && children[0]->children[0]->type == AST_RANGE && children[0]->children[0]->children.size()) {
3169 if (children[0]->children[0]->children[0]->type == AST_CONSTANT)
3170 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CONST_LHS;
3171 else
3172 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_VAR_LHS;
3173 }
3174 }
3175
3176 // remember where this is
3177 if (flags & MEM2REG_FL_INIT) {
3178 if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT))
3179 mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
3180 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_INIT;
3181 } else {
3182 if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ELSE))
3183 mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
3184 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ELSE;
3185 }
3186 }
3187
3188 lhs_children_counter = 1;
3189 }
3190
3191 if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY)
3192 {
3193 AstNode *mem = id2ast;
3194
3195 // flag if used after blocking assignment (in same proc)
3196 if ((proc_flags[mem] & AstNode::MEM2REG_FL_EQ1) && !(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_EQ2)) {
3197 mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
3198 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_EQ2;
3199 }
3200 }
3201
3202 // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg'
3203 if (type == AST_MEMORY && (get_bool_attribute("\\mem2reg") || (flags & AstNode::MEM2REG_FL_ALL) || !is_reg))
3204 mem2reg_candidates[this] |= AstNode::MEM2REG_FL_FORCED;
3205
3206 if (type == AST_MODULE && get_bool_attribute("\\mem2reg"))
3207 children_flags |= AstNode::MEM2REG_FL_ALL;
3208
3209 dict<AstNode*, uint32_t> *proc_flags_p = NULL;
3210
3211 if (type == AST_ALWAYS) {
3212 int count_edge_events = 0;
3213 for (auto child : children)
3214 if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE)
3215 count_edge_events++;
3216 if (count_edge_events != 1)
3217 children_flags |= AstNode::MEM2REG_FL_ASYNC;
3218 proc_flags_p = new dict<AstNode*, uint32_t>;
3219 }
3220
3221 if (type == AST_INITIAL) {
3222 children_flags |= AstNode::MEM2REG_FL_INIT;
3223 proc_flags_p = new dict<AstNode*, uint32_t>;
3224 }
3225
3226 uint32_t backup_flags = flags;
3227 flags |= children_flags;
3228 log_assert((flags & ~0x000000ff) == 0);
3229
3230 for (auto child : children)
3231 {
3232 if (lhs_children_counter > 0) {
3233 lhs_children_counter--;
3234 if (child->children.size() && child->children[0]->type == AST_RANGE && child->children[0]->children.size()) {
3235 for (auto c : child->children[0]->children) {
3236 if (proc_flags_p)
3237 c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags);
3238 else
3239 c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags);
3240 }
3241 }
3242 } else
3243 if (proc_flags_p)
3244 child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags);
3245 else
3246 child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags);
3247 }
3248
3249 flags &= ~children_flags | backup_flags;
3250
3251 if (proc_flags_p) {
3252 #ifndef NDEBUG
3253 for (auto it : *proc_flags_p)
3254 log_assert((it.second & ~0xff000000) == 0);
3255 #endif
3256 delete proc_flags_p;
3257 }
3258 }
3259
3260 bool AstNode::mem2reg_check(pool<AstNode*> &mem2reg_set)
3261 {
3262 if (type != AST_IDENTIFIER || !id2ast || !mem2reg_set.count(id2ast))
3263 return false;
3264
3265 if (children.empty() || children[0]->type != AST_RANGE || GetSize(children[0]->children) != 1)
3266 log_file_error(filename, linenum, "Invalid array access.\n");
3267
3268 return true;
3269 }
3270
3271 void AstNode::mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes)
3272 {
3273 log_assert(mem2reg_set.count(this) == 0);
3274
3275 if (mem2reg_set.count(id2ast))
3276 id2ast = nullptr;
3277
3278 for (size_t i = 0; i < children.size(); i++) {
3279 if (mem2reg_set.count(children[i]) > 0) {
3280 delnodes.push_back(children[i]);
3281 children.erase(children.begin() + (i--));
3282 } else {
3283 children[i]->mem2reg_remove(mem2reg_set, delnodes);
3284 }
3285 }
3286 }
3287
3288 // actually replace memories with registers
3289 bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block, AstNode *&async_block)
3290 {
3291 bool did_something = false;
3292
3293 if (type == AST_BLOCK)
3294 block = this;
3295
3296 if (type == AST_FUNCTION || type == AST_TASK)
3297 return false;
3298
3299 if (type == AST_TYPEDEF)
3300 return false;
3301
3302 if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast))
3303 {
3304 log_assert(children[0]->type == AST_CONSTANT);
3305 log_assert(children[1]->type == AST_CONSTANT);
3306 log_assert(children[2]->type == AST_CONSTANT);
3307
3308 int cursor = children[0]->asInt(false);
3309 Const data = children[1]->bitsAsConst();
3310 int length = children[2]->asInt(false);
3311
3312 if (length != 0)
3313 {
3314 AstNode *block = new AstNode(AST_INITIAL, new AstNode(AST_BLOCK));
3315 mod->children.push_back(block);
3316 block = block->children[0];
3317
3318 int wordsz = GetSize(data) / length;
3319
3320 for (int i = 0; i < length; i++) {
3321 block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+i, false))), mkconst_bits(data.extract(i*wordsz, wordsz).bits, false)));
3322 block->children.back()->children[0]->str = str;
3323 block->children.back()->children[0]->id2ast = id2ast;
3324 block->children.back()->children[0]->was_checked = true;
3325 }
3326 }
3327
3328 AstNode *newNode = new AstNode(AST_NONE);
3329 newNode->cloneInto(this);
3330 delete newNode;
3331
3332 did_something = true;
3333 }
3334
3335 if (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set))
3336 {
3337 if (async_block == NULL) {
3338 async_block = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK));
3339 mod->children.push_back(async_block);
3340 }
3341
3342 AstNode *newNode = clone();
3343 newNode->type = AST_ASSIGN_EQ;
3344 newNode->children[0]->was_checked = true;
3345 async_block->children[0]->children.push_back(newNode);
3346
3347 newNode = new AstNode(AST_NONE);
3348 newNode->cloneInto(this);
3349 delete newNode;
3350
3351 did_something = true;
3352 }
3353
3354 if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->mem2reg_check(mem2reg_set) &&
3355 children[0]->children[0]->children[0]->type != AST_CONSTANT)
3356 {
3357 std::stringstream sstr;
3358 sstr << "$mem2reg_wr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
3359 std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
3360
3361 int mem_width, mem_size, addr_bits;
3362 bool mem_signed = children[0]->id2ast->is_signed;
3363 children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
3364
3365 AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
3366 wire_addr->str = id_addr;
3367 wire_addr->is_reg = true;
3368 wire_addr->was_checked = true;
3369 wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
3370 mod->children.push_back(wire_addr);
3371 while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
3372
3373 AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
3374 wire_data->str = id_data;
3375 wire_data->is_reg = true;
3376 wire_data->was_checked = true;
3377 wire_data->is_signed = mem_signed;
3378 wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
3379 mod->children.push_back(wire_data);
3380 while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
3381
3382 log_assert(block != NULL);
3383 size_t assign_idx = 0;
3384 while (assign_idx < block->children.size() && block->children[assign_idx] != this)
3385 assign_idx++;
3386 log_assert(assign_idx < block->children.size());
3387
3388 AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
3389 assign_addr->children[0]->str = id_addr;
3390 assign_addr->children[0]->was_checked = true;
3391 block->children.insert(block->children.begin()+assign_idx+1, assign_addr);
3392
3393 AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER));
3394 case_node->children[0]->str = id_addr;
3395 for (int i = 0; i < mem_size; i++) {
3396 if (children[0]->children[0]->children[0]->type == AST_CONSTANT && int(children[0]->children[0]->children[0]->integer) != i)
3397 continue;
3398 AstNode *cond_node = new AstNode(AST_COND, AstNode::mkconst_int(i, false, addr_bits), new AstNode(AST_BLOCK));
3399 AstNode *assign_reg = new AstNode(type, new AstNode(AST_IDENTIFIER), new AstNode(AST_IDENTIFIER));
3400 if (children[0]->children.size() == 2)
3401 assign_reg->children[0]->children.push_back(children[0]->children[1]->clone());
3402 assign_reg->children[0]->str = stringf("%s[%d]", children[0]->str.c_str(), i);
3403 assign_reg->children[1]->str = id_data;
3404 cond_node->children[1]->children.push_back(assign_reg);
3405 case_node->children.push_back(cond_node);
3406 }
3407 block->children.insert(block->children.begin()+assign_idx+2, case_node);
3408
3409 children[0]->delete_children();
3410 children[0]->range_valid = false;
3411 children[0]->id2ast = NULL;
3412 children[0]->str = id_data;
3413 type = AST_ASSIGN_EQ;
3414 children[0]->was_checked = true;
3415
3416 did_something = true;
3417 }
3418
3419 if (mem2reg_check(mem2reg_set))
3420 {
3421 AstNode *bit_part_sel = NULL;
3422 if (children.size() == 2)
3423 bit_part_sel = children[1]->clone();
3424
3425 if (children[0]->children[0]->type == AST_CONSTANT)
3426 {
3427 int id = children[0]->children[0]->integer;
3428 str = stringf("%s[%d]", str.c_str(), id);
3429
3430 delete_children();
3431 range_valid = false;
3432 id2ast = NULL;
3433 }
3434 else
3435 {
3436 std::stringstream sstr;
3437 sstr << "$mem2reg_rd$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++);
3438 std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
3439
3440 int mem_width, mem_size, addr_bits;
3441 bool mem_signed = id2ast->is_signed;
3442 id2ast->meminfo(mem_width, mem_size, addr_bits);
3443
3444 AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
3445 wire_addr->str = id_addr;
3446 wire_addr->is_reg = true;
3447 wire_addr->was_checked = true;
3448 if (block)
3449 wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
3450 mod->children.push_back(wire_addr);
3451 while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
3452
3453 AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
3454 wire_data->str = id_data;
3455 wire_data->is_reg = true;
3456 wire_data->was_checked = true;
3457 wire_data->is_signed = mem_signed;
3458 if (block)
3459 wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
3460 mod->children.push_back(wire_data);
3461 while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
3462
3463 AstNode *assign_addr = new AstNode(block ? AST_ASSIGN_EQ : AST_ASSIGN, new AstNode(AST_IDENTIFIER), children[0]->children[0]->clone());
3464 assign_addr->children[0]->str = id_addr;
3465 assign_addr->children[0]->was_checked = true;
3466
3467 AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER));
3468 case_node->children[0]->str = id_addr;
3469
3470 for (int i = 0; i < mem_size; i++) {
3471 if (children[0]->children[0]->type == AST_CONSTANT && int(children[0]->children[0]->integer) != i)
3472 continue;
3473 AstNode *cond_node = new AstNode(AST_COND, AstNode::mkconst_int(i, false, addr_bits), new AstNode(AST_BLOCK));
3474 AstNode *assign_reg = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), new AstNode(AST_IDENTIFIER));
3475 assign_reg->children[0]->str = id_data;
3476 assign_reg->children[0]->was_checked = true;
3477 assign_reg->children[1]->str = stringf("%s[%d]", str.c_str(), i);
3478 cond_node->children[1]->children.push_back(assign_reg);
3479 case_node->children.push_back(cond_node);
3480 }
3481
3482 std::vector<RTLIL::State> x_bits;
3483 for (int i = 0; i < mem_width; i++)
3484 x_bits.push_back(RTLIL::State::Sx);
3485
3486 AstNode *cond_node = new AstNode(AST_COND, new AstNode(AST_DEFAULT), new AstNode(AST_BLOCK));
3487 AstNode *assign_reg = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), AstNode::mkconst_bits(x_bits, false));
3488 assign_reg->children[0]->str = id_data;
3489 assign_reg->children[0]->was_checked = true;
3490 cond_node->children[1]->children.push_back(assign_reg);
3491 case_node->children.push_back(cond_node);
3492
3493 if (block)
3494 {
3495 size_t assign_idx = 0;
3496 while (assign_idx < block->children.size() && !block->children[assign_idx]->contains(this))
3497 assign_idx++;
3498 log_assert(assign_idx < block->children.size());
3499 block->children.insert(block->children.begin()+assign_idx, case_node);
3500 block->children.insert(block->children.begin()+assign_idx, assign_addr);
3501 }
3502 else
3503 {
3504 AstNode *proc = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK));
3505 proc->children[0]->children.push_back(case_node);
3506 mod->children.push_back(proc);
3507 mod->children.push_back(assign_addr);
3508 }
3509
3510 delete_children();
3511 range_valid = false;
3512 id2ast = NULL;
3513 str = id_data;
3514 }
3515
3516 if (bit_part_sel)
3517 children.push_back(bit_part_sel);
3518
3519 did_something = true;
3520 }
3521
3522 log_assert(id2ast == NULL || mem2reg_set.count(id2ast) == 0);
3523
3524 auto children_list = children;
3525 for (size_t i = 0; i < children_list.size(); i++)
3526 if (children_list[i]->mem2reg_as_needed_pass2(mem2reg_set, mod, block, async_block))
3527 did_something = true;
3528
3529 return did_something;
3530 }
3531
3532 // calculate memory dimensions
3533 void AstNode::meminfo(int &mem_width, int &mem_size, int &addr_bits)
3534 {
3535 log_assert(type == AST_MEMORY);
3536
3537 mem_width = children[0]->range_left - children[0]->range_right + 1;
3538 mem_size = children[1]->range_left - children[1]->range_right;
3539
3540 if (mem_size < 0)
3541 mem_size *= -1;
3542 mem_size += min(children[1]->range_left, children[1]->range_right) + 1;
3543
3544 addr_bits = 1;
3545 while ((1 << addr_bits) < mem_size)
3546 addr_bits++;
3547 }
3548
3549 bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
3550 {
3551 if (type == AST_FOR)
3552 recommend_const_eval = true;
3553 if (type == AST_WHILE || type == AST_REPEAT)
3554 return true;
3555 if (type == AST_FCALL && current_scope.count(str))
3556 if (current_scope[str]->has_const_only_constructs(recommend_const_eval))
3557 return true;
3558 for (auto child : children)
3559 if (child->AstNode::has_const_only_constructs(recommend_const_eval))
3560 return true;
3561 return false;
3562 }
3563
3564 bool AstNode::is_simple_const_expr()
3565 {
3566 if (type == AST_IDENTIFIER)
3567 return false;
3568 for (auto child : children)
3569 if (!child->is_simple_const_expr())
3570 return false;
3571 return true;
3572 }
3573
3574 // helper function for AstNode::eval_const_function()
3575 void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall)
3576 {
3577 if (type == AST_IDENTIFIER && variables.count(str)) {
3578 int offset = variables.at(str).offset, width = variables.at(str).val.bits.size();
3579 if (!children.empty()) {
3580 if (children.size() != 1 || children.at(0)->type != AST_RANGE)
3581 log_file_error(filename, linenum, "Memory access in constant function is not supported\n%s:%d: ...called from here.\n",
3582 fcall->filename.c_str(), fcall->linenum);
3583 children.at(0)->replace_variables(variables, fcall);
3584 while (simplify(true, false, false, 1, -1, false, true)) { }
3585 if (!children.at(0)->range_valid)
3586 log_file_error(filename, linenum, "Non-constant range\n%s:%d: ... called from here.\n",
3587 fcall->filename.c_str(), fcall->linenum);
3588 offset = min(children.at(0)->range_left, children.at(0)->range_right);
3589 width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);
3590 }
3591 offset -= variables.at(str).offset;
3592 std::vector<RTLIL::State> &var_bits = variables.at(str).val.bits;
3593 std::vector<RTLIL::State> new_bits(var_bits.begin() + offset, var_bits.begin() + offset + width);
3594 AstNode *newNode = mkconst_bits(new_bits, variables.at(str).is_signed);
3595 newNode->cloneInto(this);
3596 delete newNode;
3597 return;
3598 }
3599
3600 for (auto &child : children)
3601 child->replace_variables(variables, fcall);
3602 }
3603
3604 // evaluate functions with all-const arguments
3605 AstNode *AstNode::eval_const_function(AstNode *fcall)
3606 {
3607 std::map<std::string, AstNode*> backup_scope;
3608 std::map<std::string, AstNode::varinfo_t> variables;
3609 AstNode *block = new AstNode(AST_BLOCK);
3610
3611 size_t argidx = 0;
3612 for (auto child : children)
3613 {
3614 if (child->type == AST_WIRE)
3615 {
3616 while (child->simplify(true, false, false, 1, -1, false, true)) { }
3617 if (!child->range_valid)
3618 log_file_error(child->filename, child->linenum, "Can't determine size of variable %s\n%s:%d: ... called from here.\n",
3619 child->str.c_str(), fcall->filename.c_str(), fcall->linenum);
3620 variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1);
3621 variables[child->str].offset = min(child->range_left, child->range_right);
3622 variables[child->str].is_signed = child->is_signed;
3623 if (child->is_input && argidx < fcall->children.size())
3624 variables[child->str].val = fcall->children.at(argidx++)->bitsAsConst(variables[child->str].val.bits.size());
3625 backup_scope[child->str] = current_scope[child->str];
3626 current_scope[child->str] = child;
3627 continue;
3628 }
3629
3630 block->children.push_back(child->clone());
3631 }
3632
3633 log_assert(variables.count(str) != 0);
3634
3635 while (!block->children.empty())
3636 {
3637 AstNode *stmt = block->children.front();
3638
3639 #if 0
3640 log("-----------------------------------\n");
3641 for (auto &it : variables)
3642 log("%20s %40s\n", it.first.c_str(), log_signal(it.second.val));
3643 stmt->dumpAst(NULL, "stmt> ");
3644 #endif
3645
3646 if (stmt->type == AST_ASSIGN_EQ)
3647 {
3648 if (stmt->children.at(0)->type == AST_IDENTIFIER && stmt->children.at(0)->children.size() != 0 &&
3649 stmt->children.at(0)->children.at(0)->type == AST_RANGE)
3650 stmt->children.at(0)->children.at(0)->replace_variables(variables, fcall);
3651 stmt->children.at(1)->replace_variables(variables, fcall);
3652 while (stmt->simplify(true, false, false, 1, -1, false, true)) { }
3653
3654 if (stmt->type != AST_ASSIGN_EQ)
3655 continue;
3656
3657 if (stmt->children.at(1)->type != AST_CONSTANT)
3658 log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here. X\n",
3659 fcall->filename.c_str(), fcall->linenum);
3660
3661 if (stmt->children.at(0)->type != AST_IDENTIFIER)
3662 log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function\n%s:%d: ... called from here.\n",
3663 fcall->filename.c_str(), fcall->linenum);
3664
3665 if (!variables.count(stmt->children.at(0)->str))
3666 log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function\n%s:%d: ... called from here.\n",
3667 fcall->filename.c_str(), fcall->linenum);
3668
3669 if (stmt->children.at(0)->children.empty()) {
3670 variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size());
3671 } else {
3672 AstNode *range = stmt->children.at(0)->children.at(0);
3673 if (!range->range_valid)
3674 log_file_error(range->filename, range->linenum, "Non-constant range\n%s:%d: ... called from here.\n",
3675 fcall->filename.c_str(), fcall->linenum);
3676 int offset = min(range->range_left, range->range_right);
3677 int width = std::abs(range->range_left - range->range_right) + 1;
3678 varinfo_t &v = variables[stmt->children.at(0)->str];
3679 RTLIL::Const r = stmt->children.at(1)->bitsAsConst(v.val.bits.size());
3680 for (int i = 0; i < width; i++)
3681 v.val.bits.at(i+offset-v.offset) = r.bits.at(i);
3682 }
3683
3684 delete block->children.front();
3685 block->children.erase(block->children.begin());
3686 continue;
3687 }
3688
3689 if (stmt->type == AST_FOR)
3690 {
3691 block->children.insert(block->children.begin(), stmt->children.at(0));
3692 stmt->children.at(3)->children.push_back(stmt->children.at(2));
3693 stmt->children.erase(stmt->children.begin() + 2);
3694 stmt->children.erase(stmt->children.begin());
3695 stmt->type = AST_WHILE;
3696 continue;
3697 }
3698
3699 if (stmt->type == AST_WHILE)
3700 {
3701 AstNode *cond = stmt->children.at(0)->clone();
3702 cond->replace_variables(variables, fcall);
3703 while (cond->simplify(true, false, false, 1, -1, false, true)) { }
3704
3705 if (cond->type != AST_CONSTANT)
3706 log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
3707 fcall->filename.c_str(), fcall->linenum);
3708
3709 if (cond->asBool()) {
3710 block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
3711 } else {
3712 delete block->children.front();
3713 block->children.erase(block->children.begin());
3714 }
3715
3716 delete cond;
3717 continue;
3718 }
3719
3720 if (stmt->type == AST_REPEAT)
3721 {
3722 AstNode *num = stmt->children.at(0)->clone();
3723 num->replace_variables(variables, fcall);
3724 while (num->simplify(true, false, false, 1, -1, false, true)) { }
3725
3726 if (num->type != AST_CONSTANT)
3727 log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
3728 fcall->filename.c_str(), fcall->linenum);
3729
3730 block->children.erase(block->children.begin());
3731 for (int i = 0; i < num->bitsAsConst().as_int(); i++)
3732 block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
3733
3734 delete stmt;
3735 delete num;
3736 continue;
3737 }
3738
3739 if (stmt->type == AST_CASE)
3740 {
3741 AstNode *expr = stmt->children.at(0)->clone();
3742 expr->replace_variables(variables, fcall);
3743 while (expr->simplify(true, false, false, 1, -1, false, true)) { }
3744
3745 AstNode *sel_case = NULL;
3746 for (size_t i = 1; i < stmt->children.size(); i++)
3747 {
3748 bool found_match = false;
3749 log_assert(stmt->children.at(i)->type == AST_COND || stmt->children.at(i)->type == AST_CONDX || stmt->children.at(i)->type == AST_CONDZ);
3750
3751 if (stmt->children.at(i)->children.front()->type == AST_DEFAULT) {
3752 sel_case = stmt->children.at(i)->children.back();
3753 continue;
3754 }
3755
3756 for (size_t j = 0; j+1 < stmt->children.at(i)->children.size() && !found_match; j++)
3757 {
3758 AstNode *cond = stmt->children.at(i)->children.at(j)->clone();
3759 cond->replace_variables(variables, fcall);
3760
3761 cond = new AstNode(AST_EQ, expr->clone(), cond);
3762 while (cond->simplify(true, false, false, 1, -1, false, true)) { }
3763
3764 if (cond->type != AST_CONSTANT)
3765 log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
3766 fcall->filename.c_str(), fcall->linenum);
3767
3768 found_match = cond->asBool();
3769 delete cond;
3770 }
3771
3772 if (found_match) {
3773 sel_case = stmt->children.at(i)->children.back();
3774 break;
3775 }
3776 }
3777
3778 block->children.erase(block->children.begin());
3779 if (sel_case)
3780 block->children.insert(block->children.begin(), sel_case->clone());
3781 delete stmt;
3782 delete expr;
3783 continue;
3784 }
3785
3786 if (stmt->type == AST_BLOCK)
3787 {
3788 block->children.erase(block->children.begin());
3789 block->children.insert(block->children.begin(), stmt->children.begin(), stmt->children.end());
3790 stmt->children.clear();
3791 delete stmt;
3792 continue;
3793 }
3794
3795 log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function\n%s:%d: ... called from here.\n",
3796 fcall->filename.c_str(), fcall->linenum);
3797 log_abort();
3798 }
3799
3800 delete block;
3801
3802 for (auto &it : backup_scope)
3803 if (it.second == NULL)
3804 current_scope.erase(it.first);
3805 else
3806 current_scope[it.first] = it.second;
3807
3808 return AstNode::mkconst_bits(variables.at(str).val.bits, variables.at(str).is_signed);
3809 }
3810
3811 YOSYS_NAMESPACE_END