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