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