Merge pull request #1927 from YosysHQ/eddie/design_remove_assert
[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 AstNode *current_scope_ast = (current_ast_mod == nullptr) ? current_ast : current_ast_mod;
1173 for (auto node : current_scope_ast->children) {
1174 //log("looking at mod scope child %s\n", type2str(node->type).c_str());
1175 switch (node->type) {
1176 case AST_PARAMETER:
1177 case AST_LOCALPARAM:
1178 case AST_WIRE:
1179 case AST_AUTOWIRE:
1180 case AST_GENVAR:
1181 case AST_MEMORY:
1182 case AST_FUNCTION:
1183 case AST_TASK:
1184 case AST_DPI_FUNCTION:
1185 //log("found child %s, %s\n", type2str(node->type).c_str(), node->str.c_str());
1186 if (str == node->str) {
1187 //log("add %s, type %s to scope\n", str.c_str(), type2str(node->type).c_str());
1188 current_scope[node->str] = node;
1189 }
1190 break;
1191 case AST_ENUM:
1192 current_scope[node->str] = node;
1193 for (auto enum_node : node->children) {
1194 log_assert(enum_node->type==AST_ENUM_ITEM);
1195 if (str == enum_node->str) {
1196 //log("\nadding enum item %s to scope\n", str.c_str());
1197 current_scope[str] = enum_node;
1198 }
1199 }
1200 break;
1201 default:
1202 break;
1203 }
1204 }
1205 }
1206 if (current_scope.count(str) == 0) {
1207 if (current_ast_mod == nullptr) {
1208 log_file_error(filename, location.first_line, "Identifier `%s' is implicitly declared outside of a module.\n", str.c_str());
1209 } else if (flag_autowire || str == "\\$global_clock") {
1210 AstNode *auto_wire = new AstNode(AST_AUTOWIRE);
1211 auto_wire->str = str;
1212 current_ast_mod->children.push_back(auto_wire);
1213 current_scope[str] = auto_wire;
1214 did_something = true;
1215 } else {
1216 log_file_error(filename, location.first_line, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
1217 }
1218 }
1219 if (id2ast != current_scope[str]) {
1220 id2ast = current_scope[str];
1221 did_something = true;
1222 }
1223 }
1224
1225 // split memory access with bit select to individual statements
1226 if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue)
1227 {
1228 if (id2ast == NULL || id2ast->type != AST_MEMORY || children[0]->children.size() != 1)
1229 log_file_error(filename, location.first_line, "Invalid bit-select on memory access!\n");
1230
1231 int mem_width, mem_size, addr_bits;
1232 id2ast->meminfo(mem_width, mem_size, addr_bits);
1233
1234 int data_range_left = id2ast->children[0]->range_left;
1235 int data_range_right = id2ast->children[0]->range_right;
1236
1237 if (id2ast->children[0]->range_swapped)
1238 std::swap(data_range_left, data_range_right);
1239
1240 std::stringstream sstr;
1241 sstr << "$mem2bits$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
1242 std::string wire_id = sstr.str();
1243
1244 AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(data_range_left, true), mkconst_int(data_range_right, true)));
1245 wire->str = wire_id;
1246 if (current_block)
1247 wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
1248 current_ast_mod->children.push_back(wire);
1249 while (wire->simplify(true, false, false, 1, -1, false, false)) { }
1250
1251 AstNode *data = clone();
1252 delete data->children[1];
1253 data->children.pop_back();
1254
1255 AstNode *assign = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), data);
1256 assign->children[0]->str = wire_id;
1257 assign->children[0]->was_checked = true;
1258
1259 if (current_block)
1260 {
1261 size_t assign_idx = 0;
1262 while (assign_idx < current_block->children.size() && current_block->children[assign_idx] != current_block_child)
1263 assign_idx++;
1264 log_assert(assign_idx < current_block->children.size());
1265 current_block->children.insert(current_block->children.begin()+assign_idx, assign);
1266 wire->is_reg = true;
1267 }
1268 else
1269 {
1270 AstNode *proc = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK));
1271 proc->children[0]->children.push_back(assign);
1272 current_ast_mod->children.push_back(proc);
1273 }
1274
1275 newNode = new AstNode(AST_IDENTIFIER, children[1]->clone());
1276 newNode->str = wire_id;
1277 newNode->id2ast = wire;
1278 goto apply_newNode;
1279 }
1280
1281 if (type == AST_WHILE)
1282 log_file_error(filename, location.first_line, "While loops are only allowed in constant functions!\n");
1283
1284 if (type == AST_REPEAT)
1285 {
1286 AstNode *count = children[0];
1287 AstNode *body = children[1];
1288
1289 // eval count expression
1290 while (count->simplify(true, false, false, stage, 32, true, false)) { }
1291
1292 if (count->type != AST_CONSTANT)
1293 log_file_error(filename, location.first_line, "Repeat loops outside must have constant repeat counts!\n");
1294
1295 // convert to a block with the body repeated n times
1296 type = AST_BLOCK;
1297 children.clear();
1298 for (int i = 0; i < count->bitsAsConst().as_int(); i++)
1299 children.insert(children.begin(), body->clone());
1300
1301 delete count;
1302 delete body;
1303 did_something = true;
1304 }
1305
1306 // unroll for loops and generate-for blocks
1307 if ((type == AST_GENFOR || type == AST_FOR) && children.size() != 0)
1308 {
1309 AstNode *init_ast = children[0];
1310 AstNode *while_ast = children[1];
1311 AstNode *next_ast = children[2];
1312 AstNode *body_ast = children[3];
1313
1314 while (body_ast->type == AST_GENBLOCK && body_ast->str.empty() &&
1315 body_ast->children.size() == 1 && body_ast->children.at(0)->type == AST_GENBLOCK)
1316 body_ast = body_ast->children.at(0);
1317
1318 if (init_ast->type != AST_ASSIGN_EQ)
1319 log_file_error(filename, location.first_line, "Unsupported 1st expression of generate for-loop!\n");
1320 if (next_ast->type != AST_ASSIGN_EQ)
1321 log_file_error(filename, location.first_line, "Unsupported 3rd expression of generate for-loop!\n");
1322
1323 if (type == AST_GENFOR) {
1324 if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_GENVAR)
1325 log_file_error(filename, location.first_line, "Left hand side of 1st expression of generate for-loop is not a gen var!\n");
1326 if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_GENVAR)
1327 log_file_error(filename, location.first_line, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n");
1328 } else {
1329 if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_WIRE)
1330 log_file_error(filename, location.first_line, "Left hand side of 1st expression of generate for-loop is not a register!\n");
1331 if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_WIRE)
1332 log_file_error(filename, location.first_line, "Left hand side of 3rd expression of generate for-loop is not a register!\n");
1333 }
1334
1335 if (init_ast->children[0]->id2ast != next_ast->children[0]->id2ast)
1336 log_file_error(filename, location.first_line, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n");
1337
1338 // eval 1st expression
1339 AstNode *varbuf = init_ast->children[1]->clone();
1340 {
1341 int expr_width_hint = -1;
1342 bool expr_sign_hint = true;
1343 varbuf->detectSignWidth(expr_width_hint, expr_sign_hint);
1344 while (varbuf->simplify(true, false, false, stage, 32, true, false)) { }
1345 }
1346
1347 if (varbuf->type != AST_CONSTANT)
1348 log_file_error(filename, location.first_line, "Right hand side of 1st expression of generate for-loop is not constant!\n");
1349
1350 auto resolved = current_scope.at(init_ast->children[0]->str);
1351 if (resolved->range_valid) {
1352 int const_size = varbuf->range_left - varbuf->range_right;
1353 int resolved_size = resolved->range_left - resolved->range_right;
1354 if (const_size < resolved_size) {
1355 for (int i = const_size; i < resolved_size; i++)
1356 varbuf->bits.push_back(resolved->is_signed ? varbuf->bits.back() : State::S0);
1357 varbuf->range_left = resolved->range_left;
1358 varbuf->range_right = resolved->range_right;
1359 varbuf->range_swapped = resolved->range_swapped;
1360 varbuf->range_valid = resolved->range_valid;
1361 }
1362 }
1363
1364 varbuf = new AstNode(AST_LOCALPARAM, varbuf);
1365 varbuf->str = init_ast->children[0]->str;
1366
1367 AstNode *backup_scope_varbuf = current_scope[varbuf->str];
1368 current_scope[varbuf->str] = varbuf;
1369
1370 size_t current_block_idx = 0;
1371 if (type == AST_FOR) {
1372 while (current_block_idx < current_block->children.size() &&
1373 current_block->children[current_block_idx] != current_block_child)
1374 current_block_idx++;
1375 }
1376
1377 while (1)
1378 {
1379 // eval 2nd expression
1380 AstNode *buf = while_ast->clone();
1381 {
1382 int expr_width_hint = -1;
1383 bool expr_sign_hint = true;
1384 buf->detectSignWidth(expr_width_hint, expr_sign_hint);
1385 while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, false)) { }
1386 }
1387
1388 if (buf->type != AST_CONSTANT)
1389 log_file_error(filename, location.first_line, "2nd expression of generate for-loop is not constant!\n");
1390
1391 if (buf->integer == 0) {
1392 delete buf;
1393 break;
1394 }
1395 delete buf;
1396
1397 // expand body
1398 int index = varbuf->children[0]->integer;
1399 if (body_ast->type == AST_GENBLOCK)
1400 buf = body_ast->clone();
1401 else
1402 buf = new AstNode(AST_GENBLOCK, body_ast->clone());
1403 if (buf->str.empty()) {
1404 std::stringstream sstr;
1405 sstr << "$genblock$" << filename << ":" << location.first_line << "$" << (autoidx++);
1406 buf->str = sstr.str();
1407 }
1408 std::map<std::string, std::string> name_map;
1409 std::stringstream sstr;
1410 sstr << buf->str << "[" << index << "].";
1411 buf->expand_genblock(varbuf->str, sstr.str(), name_map);
1412
1413 if (type == AST_GENFOR) {
1414 for (size_t i = 0; i < buf->children.size(); i++) {
1415 buf->children[i]->simplify(false, false, false, stage, -1, false, false);
1416 current_ast_mod->children.push_back(buf->children[i]);
1417 }
1418 } else {
1419 for (size_t i = 0; i < buf->children.size(); i++)
1420 current_block->children.insert(current_block->children.begin() + current_block_idx++, buf->children[i]);
1421 }
1422 buf->children.clear();
1423 delete buf;
1424
1425 // eval 3rd expression
1426 buf = next_ast->children[1]->clone();
1427 {
1428 int expr_width_hint = -1;
1429 bool expr_sign_hint = true;
1430 buf->detectSignWidth(expr_width_hint, expr_sign_hint);
1431 while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, true)) { }
1432 }
1433
1434 if (buf->type != AST_CONSTANT)
1435 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());
1436
1437 delete varbuf->children[0];
1438 varbuf->children[0] = buf;
1439 }
1440
1441 if (type == AST_FOR) {
1442 AstNode *buf = next_ast->clone();
1443 delete buf->children[1];
1444 buf->children[1] = varbuf->children[0]->clone();
1445 current_block->children.insert(current_block->children.begin() + current_block_idx++, buf);
1446 }
1447
1448 current_scope[varbuf->str] = backup_scope_varbuf;
1449 delete varbuf;
1450 delete_children();
1451 did_something = true;
1452 }
1453
1454 // check for local objects in unnamed block
1455 if (type == AST_BLOCK && str.empty())
1456 {
1457 for (size_t i = 0; i < children.size(); i++)
1458 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)
1459 log_file_error(children[i]->filename, children[i]->location.first_line, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
1460 }
1461
1462 // transform block with name
1463 if (type == AST_BLOCK && !str.empty())
1464 {
1465 std::map<std::string, std::string> name_map;
1466 expand_genblock(std::string(), str + ".", name_map);
1467
1468 std::vector<AstNode*> new_children;
1469 for (size_t i = 0; i < children.size(); i++)
1470 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) {
1471 children[i]->simplify(false, false, false, stage, -1, false, false);
1472 current_ast_mod->children.push_back(children[i]);
1473 current_scope[children[i]->str] = children[i];
1474 } else
1475 new_children.push_back(children[i]);
1476
1477 children.swap(new_children);
1478 did_something = true;
1479 str.clear();
1480 }
1481
1482 // simplify unconditional generate block
1483 if (type == AST_GENBLOCK && children.size() != 0)
1484 {
1485 if (!str.empty()) {
1486 std::map<std::string, std::string> name_map;
1487 expand_genblock(std::string(), str + ".", name_map);
1488 }
1489
1490 for (size_t i = 0; i < children.size(); i++) {
1491 children[i]->simplify(false, false, false, stage, -1, false, false);
1492 current_ast_mod->children.push_back(children[i]);
1493 }
1494
1495 children.clear();
1496 did_something = true;
1497 }
1498
1499 // simplify generate-if blocks
1500 if (type == AST_GENIF && children.size() != 0)
1501 {
1502 AstNode *buf = children[0]->clone();
1503 while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1504 if (buf->type != AST_CONSTANT) {
1505 // for (auto f : log_files)
1506 // dumpAst(f, "verilog-ast> ");
1507 log_file_error(filename, location.first_line, "Condition for generate if is not constant!\n");
1508 }
1509 if (buf->asBool() != 0) {
1510 delete buf;
1511 buf = children[1]->clone();
1512 } else {
1513 delete buf;
1514 buf = children.size() > 2 ? children[2]->clone() : NULL;
1515 }
1516
1517 if (buf)
1518 {
1519 if (buf->type != AST_GENBLOCK)
1520 buf = new AstNode(AST_GENBLOCK, buf);
1521
1522 if (!buf->str.empty()) {
1523 std::map<std::string, std::string> name_map;
1524 buf->expand_genblock(std::string(), buf->str + ".", name_map);
1525 }
1526
1527 for (size_t i = 0; i < buf->children.size(); i++) {
1528 buf->children[i]->simplify(false, false, false, stage, -1, false, false);
1529 current_ast_mod->children.push_back(buf->children[i]);
1530 }
1531
1532 buf->children.clear();
1533 delete buf;
1534 }
1535
1536 delete_children();
1537 did_something = true;
1538 }
1539
1540 // simplify generate-case blocks
1541 if (type == AST_GENCASE && children.size() != 0)
1542 {
1543 AstNode *buf = children[0]->clone();
1544 while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1545 if (buf->type != AST_CONSTANT) {
1546 // for (auto f : log_files)
1547 // dumpAst(f, "verilog-ast> ");
1548 log_file_error(filename, location.first_line, "Condition for generate case is not constant!\n");
1549 }
1550
1551 bool ref_signed = buf->is_signed;
1552 RTLIL::Const ref_value = buf->bitsAsConst();
1553 delete buf;
1554
1555 AstNode *selected_case = NULL;
1556 for (size_t i = 1; i < children.size(); i++)
1557 {
1558 log_assert(children.at(i)->type == AST_COND || children.at(i)->type == AST_CONDX || children.at(i)->type == AST_CONDZ);
1559
1560 AstNode *this_genblock = NULL;
1561 for (auto child : children.at(i)->children) {
1562 log_assert(this_genblock == NULL);
1563 if (child->type == AST_GENBLOCK)
1564 this_genblock = child;
1565 }
1566
1567 for (auto child : children.at(i)->children)
1568 {
1569 if (child->type == AST_DEFAULT) {
1570 if (selected_case == NULL)
1571 selected_case = this_genblock;
1572 continue;
1573 }
1574 if (child->type == AST_GENBLOCK)
1575 continue;
1576
1577 buf = child->clone();
1578 while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1579 if (buf->type != AST_CONSTANT) {
1580 // for (auto f : log_files)
1581 // dumpAst(f, "verilog-ast> ");
1582 log_file_error(filename, location.first_line, "Expression in generate case is not constant!\n");
1583 }
1584
1585 bool is_selected = RTLIL::const_eq(ref_value, buf->bitsAsConst(), ref_signed && buf->is_signed, ref_signed && buf->is_signed, 1).as_bool();
1586 delete buf;
1587
1588 if (is_selected) {
1589 selected_case = this_genblock;
1590 i = children.size();
1591 break;
1592 }
1593 }
1594 }
1595
1596 if (selected_case != NULL)
1597 {
1598 log_assert(selected_case->type == AST_GENBLOCK);
1599 buf = selected_case->clone();
1600
1601 if (!buf->str.empty()) {
1602 std::map<std::string, std::string> name_map;
1603 buf->expand_genblock(std::string(), buf->str + ".", name_map);
1604 }
1605
1606 for (size_t i = 0; i < buf->children.size(); i++) {
1607 buf->children[i]->simplify(false, false, false, stage, -1, false, false);
1608 current_ast_mod->children.push_back(buf->children[i]);
1609 }
1610
1611 buf->children.clear();
1612 delete buf;
1613 }
1614
1615 delete_children();
1616 did_something = true;
1617 }
1618
1619 // unroll cell arrays
1620 if (type == AST_CELLARRAY)
1621 {
1622 if (!children.at(0)->range_valid)
1623 log_file_error(filename, location.first_line, "Non-constant array range on cell array.\n");
1624
1625 newNode = new AstNode(AST_GENBLOCK);
1626 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;
1627
1628 for (int i = 0; i < num; i++) {
1629 int idx = children.at(0)->range_left > children.at(0)->range_right ? children.at(0)->range_right + i : children.at(0)->range_right - i;
1630 AstNode *new_cell = children.at(1)->clone();
1631 newNode->children.push_back(new_cell);
1632 new_cell->str += stringf("[%d]", idx);
1633 if (new_cell->type == AST_PRIMITIVE) {
1634 log_file_error(filename, location.first_line, "Cell arrays of primitives are currently not supported.\n");
1635 } else {
1636 log_assert(new_cell->children.at(0)->type == AST_CELLTYPE);
1637 new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str.c_str());
1638 }
1639 }
1640
1641 goto apply_newNode;
1642 }
1643
1644 // replace primitives with assignments
1645 if (type == AST_PRIMITIVE)
1646 {
1647 if (children.size() < 2)
1648 log_file_error(filename, location.first_line, "Insufficient number of arguments for primitive `%s'!\n", str.c_str());
1649
1650 std::vector<AstNode*> children_list;
1651 for (auto child : children) {
1652 log_assert(child->type == AST_ARGUMENT);
1653 log_assert(child->children.size() == 1);
1654 children_list.push_back(child->children[0]);
1655 child->children.clear();
1656 delete child;
1657 }
1658 children.clear();
1659
1660 if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1")
1661 {
1662 if (children_list.size() != 3)
1663 log_file_error(filename, location.first_line, "Invalid number of arguments for primitive `%s'!\n", str.c_str());
1664
1665 std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz);
1666
1667 AstNode *mux_input = children_list.at(1);
1668 if (str == "notif0" || str == "notif1") {
1669 mux_input = new AstNode(AST_BIT_NOT, mux_input);
1670 }
1671 AstNode *node = new AstNode(AST_TERNARY, children_list.at(2));
1672 if (str == "bufif0") {
1673 node->children.push_back(AstNode::mkconst_bits(z_const, false));
1674 node->children.push_back(mux_input);
1675 } else {
1676 node->children.push_back(mux_input);
1677 node->children.push_back(AstNode::mkconst_bits(z_const, false));
1678 }
1679
1680 str.clear();
1681 type = AST_ASSIGN;
1682 children.push_back(children_list.at(0));
1683 children.back()->was_checked = true;
1684 children.push_back(node);
1685 did_something = true;
1686 }
1687 else
1688 {
1689 AstNodeType op_type = AST_NONE;
1690 bool invert_results = false;
1691
1692 if (str == "and")
1693 op_type = AST_BIT_AND;
1694 if (str == "nand")
1695 op_type = AST_BIT_AND, invert_results = true;
1696 if (str == "or")
1697 op_type = AST_BIT_OR;
1698 if (str == "nor")
1699 op_type = AST_BIT_OR, invert_results = true;
1700 if (str == "xor")
1701 op_type = AST_BIT_XOR;
1702 if (str == "xnor")
1703 op_type = AST_BIT_XOR, invert_results = true;
1704 if (str == "buf")
1705 op_type = AST_POS;
1706 if (str == "not")
1707 op_type = AST_POS, invert_results = true;
1708 log_assert(op_type != AST_NONE);
1709
1710 AstNode *node = children_list[1];
1711 if (op_type != AST_POS)
1712 for (size_t i = 2; i < children_list.size(); i++)
1713 node = new AstNode(op_type, node, children_list[i]);
1714 if (invert_results)
1715 node = new AstNode(AST_BIT_NOT, node);
1716
1717 str.clear();
1718 type = AST_ASSIGN;
1719 children.push_back(children_list[0]);
1720 children.back()->was_checked = true;
1721 children.push_back(node);
1722 did_something = true;
1723 }
1724 }
1725
1726 // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
1727 // a big case block that selects the correct single-bit assignment.
1728 if (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) {
1729 if (children[0]->type != AST_IDENTIFIER || children[0]->children.size() == 0)
1730 goto skip_dynamic_range_lvalue_expansion;
1731 if (children[0]->children[0]->range_valid || did_something)
1732 goto skip_dynamic_range_lvalue_expansion;
1733 if (children[0]->id2ast == NULL || children[0]->id2ast->type != AST_WIRE)
1734 goto skip_dynamic_range_lvalue_expansion;
1735 if (!children[0]->id2ast->range_valid)
1736 goto skip_dynamic_range_lvalue_expansion;
1737 int source_width = children[0]->id2ast->range_left - children[0]->id2ast->range_right + 1;
1738 int result_width = 1;
1739 AstNode *shift_expr = NULL;
1740 AstNode *range = children[0]->children[0];
1741 if (range->children.size() == 1) {
1742 shift_expr = range->children[0]->clone();
1743 } else {
1744 shift_expr = range->children[1]->clone();
1745 AstNode *left_at_zero_ast = range->children[0]->clone();
1746 AstNode *right_at_zero_ast = range->children[1]->clone();
1747 while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
1748 while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
1749 if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
1750 log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
1751 result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
1752 }
1753 did_something = true;
1754 newNode = new AstNode(AST_CASE, shift_expr);
1755 for (int i = 0; i < source_width; i++) {
1756 int start_bit = children[0]->id2ast->range_right + i;
1757 AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true));
1758 AstNode *lvalue = children[0]->clone();
1759 lvalue->delete_children();
1760 int end_bit = std::min(start_bit+result_width,source_width) - 1;
1761 lvalue->children.push_back(new AstNode(AST_RANGE,
1762 mkconst_int(end_bit, true), mkconst_int(start_bit, true)));
1763 cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone())));
1764 newNode->children.push_back(cond);
1765 }
1766 goto apply_newNode;
1767 }
1768 skip_dynamic_range_lvalue_expansion:;
1769
1770 if (stage > 1 && (type == AST_ASSERT || type == AST_ASSUME || type == AST_LIVE || type == AST_FAIR || type == AST_COVER) && current_block != NULL)
1771 {
1772 std::stringstream sstr;
1773 sstr << "$formal$" << filename << ":" << location.first_line << "$" << (autoidx++);
1774 std::string id_check = sstr.str() + "_CHECK", id_en = sstr.str() + "_EN";
1775
1776 AstNode *wire_check = new AstNode(AST_WIRE);
1777 wire_check->str = id_check;
1778 wire_check->was_checked = true;
1779 current_ast_mod->children.push_back(wire_check);
1780 current_scope[wire_check->str] = wire_check;
1781 while (wire_check->simplify(true, false, false, 1, -1, false, false)) { }
1782
1783 AstNode *wire_en = new AstNode(AST_WIRE);
1784 wire_en->str = id_en;
1785 wire_en->was_checked = true;
1786 current_ast_mod->children.push_back(wire_en);
1787 if (current_always_clocked) {
1788 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)))));
1789 current_ast_mod->children.back()->children[0]->children[0]->children[0]->str = id_en;
1790 current_ast_mod->children.back()->children[0]->children[0]->children[0]->was_checked = true;
1791 }
1792 current_scope[wire_en->str] = wire_en;
1793 while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
1794
1795 AstNode *check_defval;
1796 if (type == AST_LIVE || type == AST_FAIR) {
1797 check_defval = new AstNode(AST_REDUCE_BOOL, children[0]->clone());
1798 } else {
1799 std::vector<RTLIL::State> x_bit;
1800 x_bit.push_back(RTLIL::State::Sx);
1801 check_defval = mkconst_bits(x_bit, false);
1802 }
1803
1804 AstNode *assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), check_defval);
1805 assign_check->children[0]->str = id_check;
1806 assign_check->children[0]->was_checked = true;
1807
1808 AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, 1));
1809 assign_en->children[0]->str = id_en;
1810 assign_en->children[0]->was_checked = true;
1811
1812 AstNode *default_signals = new AstNode(AST_BLOCK);
1813 default_signals->children.push_back(assign_check);
1814 default_signals->children.push_back(assign_en);
1815 current_top_block->children.insert(current_top_block->children.begin(), default_signals);
1816
1817 if (type == AST_LIVE || type == AST_FAIR) {
1818 assign_check = nullptr;
1819 } else {
1820 assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_REDUCE_BOOL, children[0]->clone()));
1821 assign_check->children[0]->str = id_check;
1822 assign_check->children[0]->was_checked = true;
1823 }
1824
1825 if (current_always == nullptr || current_always->type != AST_INITIAL) {
1826 assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(1, false, 1));
1827 } else {
1828 assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_FCALL));
1829 assign_en->children[1]->str = "\\$initstate";
1830 }
1831 assign_en->children[0]->str = id_en;
1832 assign_en->children[0]->was_checked = true;
1833
1834 newNode = new AstNode(AST_BLOCK);
1835 if (assign_check != nullptr)
1836 newNode->children.push_back(assign_check);
1837 newNode->children.push_back(assign_en);
1838
1839 AstNode *assertnode = new AstNode(type);
1840 assertnode->location = location;
1841 assertnode->str = str;
1842 assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
1843 assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
1844 assertnode->children[0]->str = id_check;
1845 assertnode->children[1]->str = id_en;
1846 assertnode->attributes.swap(attributes);
1847 current_ast_mod->children.push_back(assertnode);
1848
1849 goto apply_newNode;
1850 }
1851
1852 if (stage > 1 && (type == AST_ASSERT || type == AST_ASSUME || type == AST_LIVE || type == AST_FAIR || type == AST_COVER) && children.size() == 1)
1853 {
1854 children.push_back(mkconst_int(1, false, 1));
1855 did_something = true;
1856 }
1857
1858 // found right-hand side identifier for memory -> replace with memory read port
1859 if (stage > 1 && type == AST_IDENTIFIER && id2ast != NULL && id2ast->type == AST_MEMORY && !in_lvalue &&
1860 children.size() == 1 && children[0]->type == AST_RANGE && children[0]->children.size() == 1) {
1861 newNode = new AstNode(AST_MEMRD, children[0]->children[0]->clone());
1862 newNode->str = str;
1863 newNode->id2ast = id2ast;
1864 goto apply_newNode;
1865 }
1866
1867 // assignment with nontrivial member in left-hand concat expression -> split assignment
1868 if ((type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) && children[0]->type == AST_CONCAT && width_hint > 0)
1869 {
1870 bool found_nontrivial_member = false;
1871
1872 for (auto child : children[0]->children) {
1873 if (child->type == AST_IDENTIFIER && child->id2ast != NULL && child->id2ast->type == AST_MEMORY)
1874 found_nontrivial_member = true;
1875 }
1876
1877 if (found_nontrivial_member)
1878 {
1879 newNode = new AstNode(AST_BLOCK);
1880
1881 AstNode *wire_tmp = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(width_hint-1, true), mkconst_int(0, true)));
1882 wire_tmp->str = stringf("$splitcmplxassign$%s:%d$%d", filename.c_str(), location.first_line, autoidx++);
1883 current_ast_mod->children.push_back(wire_tmp);
1884 current_scope[wire_tmp->str] = wire_tmp;
1885 wire_tmp->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
1886 while (wire_tmp->simplify(true, false, false, 1, -1, false, false)) { }
1887 wire_tmp->is_logic = true;
1888
1889 AstNode *wire_tmp_id = new AstNode(AST_IDENTIFIER);
1890 wire_tmp_id->str = wire_tmp->str;
1891
1892 newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, wire_tmp_id, children[1]->clone()));
1893 newNode->children.back()->was_checked = true;
1894
1895 int cursor = 0;
1896 for (auto child : children[0]->children)
1897 {
1898 int child_width_hint = -1;
1899 bool child_sign_hint = true;
1900 child->detectSignWidth(child_width_hint, child_sign_hint);
1901
1902 AstNode *rhs = wire_tmp_id->clone();
1903 rhs->children.push_back(new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+child_width_hint-1, true), AstNode::mkconst_int(cursor, true)));
1904 newNode->children.push_back(new AstNode(type, child->clone(), rhs));
1905
1906 cursor += child_width_hint;
1907 }
1908
1909 goto apply_newNode;
1910 }
1911 }
1912
1913 // assignment with memory in left-hand side expression -> replace with memory write port
1914 if (stage > 1 && (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) && children[0]->type == AST_IDENTIFIER &&
1915 children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY && children[0]->id2ast->children.size() >= 2 &&
1916 children[0]->id2ast->children[0]->range_valid && children[0]->id2ast->children[1]->range_valid &&
1917 (children[0]->children.size() == 1 || children[0]->children.size() == 2) && children[0]->children[0]->type == AST_RANGE)
1918 {
1919 std::stringstream sstr;
1920 sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
1921 std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN";
1922
1923 int mem_width, mem_size, addr_bits;
1924 bool mem_signed = children[0]->id2ast->is_signed;
1925 children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
1926
1927 newNode = new AstNode(AST_BLOCK);
1928 AstNode *defNode = new AstNode(AST_BLOCK);
1929
1930 int data_range_left = children[0]->id2ast->children[0]->range_left;
1931 int data_range_right = children[0]->id2ast->children[0]->range_right;
1932 int mem_data_range_offset = std::min(data_range_left, data_range_right);
1933
1934 int addr_width_hint = -1;
1935 bool addr_sign_hint = true;
1936 children[0]->children[0]->children[0]->detectSignWidthWorker(addr_width_hint, addr_sign_hint);
1937 addr_bits = std::max(addr_bits, addr_width_hint);
1938
1939 std::vector<RTLIL::State> x_bits_addr, x_bits_data, set_bits_en;
1940 for (int i = 0; i < addr_bits; i++)
1941 x_bits_addr.push_back(RTLIL::State::Sx);
1942 for (int i = 0; i < mem_width; i++)
1943 x_bits_data.push_back(RTLIL::State::Sx);
1944 for (int i = 0; i < mem_width; i++)
1945 set_bits_en.push_back(RTLIL::State::S1);
1946
1947 AstNode *node_addr = nullptr;
1948 if (children[0]->children[0]->children[0]->isConst()) {
1949 node_addr = children[0]->children[0]->children[0]->clone();
1950 } else {
1951 AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
1952 wire_addr->str = id_addr;
1953 wire_addr->was_checked = true;
1954 current_ast_mod->children.push_back(wire_addr);
1955 current_scope[wire_addr->str] = wire_addr;
1956 while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
1957
1958 AstNode *assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false));
1959 assign_addr->children[0]->str = id_addr;
1960 assign_addr->children[0]->was_checked = true;
1961 defNode->children.push_back(assign_addr);
1962
1963 assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
1964 assign_addr->children[0]->str = id_addr;
1965 assign_addr->children[0]->was_checked = true;
1966 newNode->children.push_back(assign_addr);
1967
1968 node_addr = new AstNode(AST_IDENTIFIER);
1969 node_addr->str = id_addr;
1970 }
1971
1972 AstNode *node_data = nullptr;
1973 if (children[0]->children.size() == 1 && children[1]->isConst()) {
1974 node_data = children[1]->clone();
1975 } else {
1976 AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
1977 wire_data->str = id_data;
1978 wire_data->was_checked = true;
1979 wire_data->is_signed = mem_signed;
1980 current_ast_mod->children.push_back(wire_data);
1981 current_scope[wire_data->str] = wire_data;
1982 while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
1983
1984 AstNode *assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false));
1985 assign_data->children[0]->str = id_data;
1986 assign_data->children[0]->was_checked = true;
1987 defNode->children.push_back(assign_data);
1988
1989 node_data = new AstNode(AST_IDENTIFIER);
1990 node_data->str = id_data;
1991 }
1992
1993 AstNode *node_en = nullptr;
1994 if (current_always->type == AST_INITIAL) {
1995 node_en = AstNode::mkconst_int(1, false);
1996 } else {
1997 AstNode *wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
1998 wire_en->str = id_en;
1999 wire_en->was_checked = true;
2000 current_ast_mod->children.push_back(wire_en);
2001 current_scope[wire_en->str] = wire_en;
2002 while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
2003
2004 AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width));
2005 assign_en->children[0]->str = id_en;
2006 assign_en->children[0]->was_checked = true;
2007 defNode->children.push_back(assign_en);
2008
2009 node_en = new AstNode(AST_IDENTIFIER);
2010 node_en->str = id_en;
2011 }
2012
2013 if (!defNode->children.empty())
2014 current_top_block->children.insert(current_top_block->children.begin(), defNode);
2015 else
2016 delete defNode;
2017
2018 AstNode *assign_data = nullptr;
2019 AstNode *assign_en = nullptr;
2020 if (children[0]->children.size() == 2)
2021 {
2022 if (children[0]->children[1]->range_valid)
2023 {
2024 int offset = children[0]->children[1]->range_right;
2025 int width = children[0]->children[1]->range_left - offset + 1;
2026 offset -= mem_data_range_offset;
2027
2028 std::vector<RTLIL::State> padding_x(offset, RTLIL::State::Sx);
2029
2030 assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
2031 new AstNode(AST_CONCAT, mkconst_bits(padding_x, false), children[1]->clone()));
2032 assign_data->children[0]->str = id_data;
2033 assign_data->children[0]->was_checked = true;
2034
2035 if (current_always->type != AST_INITIAL) {
2036 for (int i = 0; i < mem_width; i++)
2037 set_bits_en[i] = offset <= i && i < offset+width ? RTLIL::State::S1 : RTLIL::State::S0;
2038 assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
2039 assign_en->children[0]->str = id_en;
2040 assign_en->children[0]->was_checked = true;
2041 }
2042 }
2043 else
2044 {
2045 AstNode *the_range = children[0]->children[1];
2046 AstNode *left_at_zero_ast = the_range->children[0]->clone();
2047 AstNode *right_at_zero_ast = the_range->children.size() >= 2 ? the_range->children[1]->clone() : left_at_zero_ast->clone();
2048 AstNode *offset_ast = right_at_zero_ast->clone();
2049
2050 if (mem_data_range_offset)
2051 offset_ast = new AstNode(AST_SUB, offset_ast, mkconst_int(mem_data_range_offset, true));
2052
2053 while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
2054 while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
2055 if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
2056 log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
2057 int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
2058
2059 assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
2060 new AstNode(AST_SHIFT_LEFT, children[1]->clone(), offset_ast->clone()));
2061 assign_data->children[0]->str = id_data;
2062 assign_data->children[0]->was_checked = true;
2063
2064 if (current_always->type != AST_INITIAL) {
2065 for (int i = 0; i < mem_width; i++)
2066 set_bits_en[i] = i < width ? RTLIL::State::S1 : RTLIL::State::S0;
2067 assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
2068 new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone()));
2069 assign_en->children[0]->str = id_en;
2070 assign_en->children[0]->was_checked = true;
2071 }
2072
2073 delete left_at_zero_ast;
2074 delete right_at_zero_ast;
2075 delete offset_ast;
2076 }
2077 }
2078 else
2079 {
2080 if (!(children[0]->children.size() == 1 && children[1]->isConst())) {
2081 assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone());
2082 assign_data->children[0]->str = id_data;
2083 assign_data->children[0]->was_checked = true;
2084 }
2085
2086 if (current_always->type != AST_INITIAL) {
2087 assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
2088 assign_en->children[0]->str = id_en;
2089 assign_en->children[0]->was_checked = true;
2090 }
2091 }
2092 if (assign_data)
2093 newNode->children.push_back(assign_data);
2094 if (assign_en)
2095 newNode->children.push_back(assign_en);
2096
2097 AstNode *wrnode = new AstNode(current_always->type == AST_INITIAL ? AST_MEMINIT : AST_MEMWR, node_addr, node_data, node_en);
2098 wrnode->str = children[0]->str;
2099 wrnode->id2ast = children[0]->id2ast;
2100 current_ast_mod->children.push_back(wrnode);
2101
2102 if (newNode->children.empty()) {
2103 delete newNode;
2104 newNode = new AstNode();
2105 }
2106 goto apply_newNode;
2107 }
2108
2109 // replace function and task calls with the code from the function or task
2110 if ((type == AST_FCALL || type == AST_TCALL) && !str.empty())
2111 {
2112 if (type == AST_FCALL)
2113 {
2114 if (str == "\\$initstate")
2115 {
2116 int myidx = autoidx++;
2117
2118 AstNode *wire = new AstNode(AST_WIRE);
2119 wire->str = stringf("$initstate$%d_wire", myidx);
2120 current_ast_mod->children.push_back(wire);
2121 while (wire->simplify(true, false, false, 1, -1, false, false)) { }
2122
2123 AstNode *cell = new AstNode(AST_CELL, new AstNode(AST_CELLTYPE), new AstNode(AST_ARGUMENT, new AstNode(AST_IDENTIFIER)));
2124 cell->str = stringf("$initstate$%d", myidx);
2125 cell->children[0]->str = "$initstate";
2126 cell->children[1]->str = "\\Y";
2127 cell->children[1]->children[0]->str = wire->str;
2128 cell->children[1]->children[0]->id2ast = wire;
2129 current_ast_mod->children.push_back(cell);
2130 while (cell->simplify(true, false, false, 1, -1, false, false)) { }
2131
2132 newNode = new AstNode(AST_IDENTIFIER);
2133 newNode->str = wire->str;
2134 newNode->id2ast = wire;
2135 goto apply_newNode;
2136 }
2137
2138 if (str == "\\$past")
2139 {
2140 if (width_hint < 0)
2141 goto replace_fcall_later;
2142
2143 int num_steps = 1;
2144
2145 if (GetSize(children) != 1 && GetSize(children) != 2)
2146 log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1 or 2.\n",
2147 RTLIL::unescape_id(str).c_str(), int(children.size()));
2148
2149 if (!current_always_clocked)
2150 log_file_error(filename, location.first_line, "System function %s is only allowed in clocked blocks.\n",
2151 RTLIL::unescape_id(str).c_str());
2152
2153 if (GetSize(children) == 2)
2154 {
2155 AstNode *buf = children[1]->clone();
2156 while (buf->simplify(true, false, false, stage, -1, false, false)) { }
2157 if (buf->type != AST_CONSTANT)
2158 log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str());
2159
2160 num_steps = buf->asInt(true);
2161 delete buf;
2162 }
2163
2164 AstNode *block = nullptr;
2165
2166 for (auto child : current_always->children)
2167 if (child->type == AST_BLOCK)
2168 block = child;
2169
2170 log_assert(block != nullptr);
2171
2172 if (num_steps == 0) {
2173 newNode = children[0]->clone();
2174 goto apply_newNode;
2175 }
2176
2177 int myidx = autoidx++;
2178 AstNode *outreg = nullptr;
2179
2180 for (int i = 0; i < num_steps; i++)
2181 {
2182 AstNode *reg = new AstNode(AST_WIRE, new AstNode(AST_RANGE,
2183 mkconst_int(width_hint-1, true), mkconst_int(0, true)));
2184
2185 reg->str = stringf("$past$%s:%d$%d$%d", filename.c_str(), location.first_line, myidx, i);
2186 reg->is_reg = true;
2187
2188 current_ast_mod->children.push_back(reg);
2189
2190 while (reg->simplify(true, false, false, 1, -1, false, false)) { }
2191
2192 AstNode *regid = new AstNode(AST_IDENTIFIER);
2193 regid->str = reg->str;
2194 regid->id2ast = reg;
2195 regid->was_checked = true;
2196
2197 AstNode *rhs = nullptr;
2198
2199 if (outreg == nullptr) {
2200 rhs = children.at(0)->clone();
2201 } else {
2202 rhs = new AstNode(AST_IDENTIFIER);
2203 rhs->str = outreg->str;
2204 rhs->id2ast = outreg;
2205 }
2206
2207 block->children.push_back(new AstNode(AST_ASSIGN_LE, regid, rhs));
2208 outreg = reg;
2209 }
2210
2211 newNode = new AstNode(AST_IDENTIFIER);
2212 newNode->str = outreg->str;
2213 newNode->id2ast = outreg;
2214 goto apply_newNode;
2215 }
2216
2217 if (str == "\\$stable" || str == "\\$rose" || str == "\\$fell" || str == "\\$changed")
2218 {
2219 if (GetSize(children) != 1)
2220 log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n",
2221 RTLIL::unescape_id(str).c_str(), int(children.size()));
2222
2223 if (!current_always_clocked)
2224 log_file_error(filename, location.first_line, "System function %s is only allowed in clocked blocks.\n",
2225 RTLIL::unescape_id(str).c_str());
2226
2227 AstNode *present = children.at(0)->clone();
2228 AstNode *past = clone();
2229 past->str = "\\$past";
2230
2231 if (str == "\\$stable")
2232 newNode = new AstNode(AST_EQ, past, present);
2233
2234 else if (str == "\\$changed")
2235 newNode = new AstNode(AST_NE, past, present);
2236
2237 else if (str == "\\$rose")
2238 newNode = new AstNode(AST_LOGIC_AND,
2239 new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, past, mkconst_int(1,false))),
2240 new AstNode(AST_BIT_AND, present, mkconst_int(1,false)));
2241
2242 else if (str == "\\$fell")
2243 newNode = new AstNode(AST_LOGIC_AND,
2244 new AstNode(AST_BIT_AND, past, mkconst_int(1,false)),
2245 new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, present, mkconst_int(1,false))));
2246
2247 else
2248 log_abort();
2249
2250 goto apply_newNode;
2251 }
2252
2253 // $anyconst and $anyseq are mapped in AstNode::genRTLIL()
2254 if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq") {
2255 recursion_counter--;
2256 return false;
2257 }
2258
2259 if (str == "\\$clog2")
2260 {
2261 if (children.size() != 1)
2262 log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n",
2263 RTLIL::unescape_id(str).c_str(), int(children.size()));
2264
2265 AstNode *buf = children[0]->clone();
2266 while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2267 if (buf->type != AST_CONSTANT)
2268 log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str());
2269
2270 RTLIL::Const arg_value = buf->bitsAsConst();
2271 if (arg_value.as_bool())
2272 arg_value = const_sub(arg_value, 1, false, false, GetSize(arg_value));
2273 delete buf;
2274
2275 uint32_t result = 0;
2276 for (size_t i = 0; i < arg_value.bits.size(); i++)
2277 if (arg_value.bits.at(i) == RTLIL::State::S1)
2278 result = i + 1;
2279
2280 newNode = mkconst_int(result, true);
2281 goto apply_newNode;
2282 }
2283
2284 if (str == "\\$size" || str == "\\$bits")
2285 {
2286 if (str == "\\$bits" && children.size() != 1)
2287 log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n",
2288 RTLIL::unescape_id(str).c_str(), int(children.size()));
2289
2290 if (str == "\\$size" && children.size() != 1 && children.size() != 2)
2291 log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1 or 2.\n",
2292 RTLIL::unescape_id(str).c_str(), int(children.size()));
2293
2294 int dim = 1;
2295 if (str == "\\$size" && children.size() == 2) {
2296 AstNode *buf = children[1]->clone();
2297 // Evaluate constant expression
2298 while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2299 dim = buf->asInt(false);
2300 delete buf;
2301 }
2302 AstNode *buf = children[0]->clone();
2303 int mem_depth = 1;
2304 AstNode *id_ast = NULL;
2305
2306 // Is this needed?
2307 //while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2308 buf->detectSignWidth(width_hint, sign_hint);
2309
2310 if (buf->type == AST_IDENTIFIER) {
2311 id_ast = buf->id2ast;
2312 if (id_ast == NULL && current_scope.count(buf->str))
2313 id_ast = current_scope.at(buf->str);
2314 if (!id_ast)
2315 log_file_error(filename, location.first_line, "Failed to resolve identifier %s for width detection!\n", buf->str.c_str());
2316 if (id_ast->type == AST_MEMORY) {
2317 // We got here only if the argument is a memory
2318 // Otherwise $size() and $bits() return the expression width
2319 AstNode *mem_range = id_ast->children[1];
2320 if (str == "\\$bits") {
2321 if (mem_range->type == AST_RANGE) {
2322 if (!mem_range->range_valid)
2323 log_file_error(filename, location.first_line, "Failed to detect width of memory access `%s'!\n", buf->str.c_str());
2324 mem_depth = mem_range->range_left - mem_range->range_right + 1;
2325 } else
2326 log_file_error(filename, location.first_line, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str());
2327 } else {
2328 // $size()
2329 if (mem_range->type == AST_RANGE) {
2330 if (!mem_range->range_valid)
2331 log_file_error(filename, location.first_line, "Failed to detect width of memory access `%s'!\n", buf->str.c_str());
2332 int dims;
2333 if (id_ast->multirange_dimensions.empty())
2334 dims = 1;
2335 else
2336 dims = GetSize(id_ast->multirange_dimensions)/2;
2337 if (dim == 1)
2338 width_hint = (dims > 1) ? id_ast->multirange_dimensions[1] : (mem_range->range_left - mem_range->range_right + 1);
2339 else if (dim <= dims) {
2340 width_hint = id_ast->multirange_dimensions[2*dim-1];
2341 } else if ((dim > dims+1) || (dim < 0))
2342 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);
2343 } else
2344 log_file_error(filename, location.first_line, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str());
2345 }
2346 }
2347 }
2348 delete buf;
2349
2350 newNode = mkconst_int(width_hint * mem_depth, false);
2351 goto apply_newNode;
2352 }
2353
2354 if (str == "\\$ln" || str == "\\$log10" || str == "\\$exp" || str == "\\$sqrt" || str == "\\$pow" ||
2355 str == "\\$floor" || str == "\\$ceil" || str == "\\$sin" || str == "\\$cos" || str == "\\$tan" ||
2356 str == "\\$asin" || str == "\\$acos" || str == "\\$atan" || str == "\\$atan2" || str == "\\$hypot" ||
2357 str == "\\$sinh" || str == "\\$cosh" || str == "\\$tanh" || str == "\\$asinh" || str == "\\$acosh" || str == "\\$atanh" ||
2358 str == "\\$rtoi" || str == "\\$itor")
2359 {
2360 bool func_with_two_arguments = str == "\\$pow" || str == "\\$atan2" || str == "\\$hypot";
2361 double x = 0, y = 0;
2362
2363 if (func_with_two_arguments) {
2364 if (children.size() != 2)
2365 log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 2.\n",
2366 RTLIL::unescape_id(str).c_str(), int(children.size()));
2367 } else {
2368 if (children.size() != 1)
2369 log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n",
2370 RTLIL::unescape_id(str).c_str(), int(children.size()));
2371 }
2372
2373 if (children.size() >= 1) {
2374 while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2375 if (!children[0]->isConst())
2376 log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant argument.\n",
2377 RTLIL::unescape_id(str).c_str());
2378 int child_width_hint = width_hint;
2379 bool child_sign_hint = sign_hint;
2380 children[0]->detectSignWidth(child_width_hint, child_sign_hint);
2381 x = children[0]->asReal(child_sign_hint);
2382 }
2383
2384 if (children.size() >= 2) {
2385 while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2386 if (!children[1]->isConst())
2387 log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant argument.\n",
2388 RTLIL::unescape_id(str).c_str());
2389 int child_width_hint = width_hint;
2390 bool child_sign_hint = sign_hint;
2391 children[1]->detectSignWidth(child_width_hint, child_sign_hint);
2392 y = children[1]->asReal(child_sign_hint);
2393 }
2394
2395 if (str == "\\$rtoi") {
2396 newNode = AstNode::mkconst_int(x, true);
2397 } else {
2398 newNode = new AstNode(AST_REALVALUE);
2399 if (str == "\\$ln") newNode->realvalue = ::log(x);
2400 else if (str == "\\$log10") newNode->realvalue = ::log10(x);
2401 else if (str == "\\$exp") newNode->realvalue = ::exp(x);
2402 else if (str == "\\$sqrt") newNode->realvalue = ::sqrt(x);
2403 else if (str == "\\$pow") newNode->realvalue = ::pow(x, y);
2404 else if (str == "\\$floor") newNode->realvalue = ::floor(x);
2405 else if (str == "\\$ceil") newNode->realvalue = ::ceil(x);
2406 else if (str == "\\$sin") newNode->realvalue = ::sin(x);
2407 else if (str == "\\$cos") newNode->realvalue = ::cos(x);
2408 else if (str == "\\$tan") newNode->realvalue = ::tan(x);
2409 else if (str == "\\$asin") newNode->realvalue = ::asin(x);
2410 else if (str == "\\$acos") newNode->realvalue = ::acos(x);
2411 else if (str == "\\$atan") newNode->realvalue = ::atan(x);
2412 else if (str == "\\$atan2") newNode->realvalue = ::atan2(x, y);
2413 else if (str == "\\$hypot") newNode->realvalue = ::hypot(x, y);
2414 else if (str == "\\$sinh") newNode->realvalue = ::sinh(x);
2415 else if (str == "\\$cosh") newNode->realvalue = ::cosh(x);
2416 else if (str == "\\$tanh") newNode->realvalue = ::tanh(x);
2417 else if (str == "\\$asinh") newNode->realvalue = ::asinh(x);
2418 else if (str == "\\$acosh") newNode->realvalue = ::acosh(x);
2419 else if (str == "\\$atanh") newNode->realvalue = ::atanh(x);
2420 else if (str == "\\$itor") newNode->realvalue = x;
2421 else log_abort();
2422 }
2423 goto apply_newNode;
2424 }
2425
2426 if (str == "\\$sformatf") {
2427 AstNode *node_string = children[0];
2428 while (node_string->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2429 if (node_string->type != AST_CONSTANT)
2430 log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str());
2431 std::string sformat = node_string->bitsAsConst().decode_string();
2432 std::string sout = process_format_str(sformat, 1, stage, width_hint, sign_hint);
2433 newNode = AstNode::mkconst_str(sout);
2434 goto apply_newNode;
2435 }
2436
2437 if (current_scope.count(str) != 0 && current_scope[str]->type == AST_DPI_FUNCTION)
2438 {
2439 AstNode *dpi_decl = current_scope[str];
2440
2441 std::string rtype, fname;
2442 std::vector<std::string> argtypes;
2443 std::vector<AstNode*> args;
2444
2445 rtype = RTLIL::unescape_id(dpi_decl->children.at(0)->str);
2446 fname = RTLIL::unescape_id(dpi_decl->children.at(1)->str);
2447
2448 for (int i = 2; i < GetSize(dpi_decl->children); i++)
2449 {
2450 if (i-2 >= GetSize(children))
2451 log_file_error(filename, location.first_line, "Insufficient number of arguments in DPI function call.\n");
2452
2453 argtypes.push_back(RTLIL::unescape_id(dpi_decl->children.at(i)->str));
2454 args.push_back(children.at(i-2)->clone());
2455 while (args.back()->simplify(true, false, false, stage, -1, false, true)) { }
2456
2457 if (args.back()->type != AST_CONSTANT && args.back()->type != AST_REALVALUE)
2458 log_file_error(filename, location.first_line, "Failed to evaluate DPI function with non-constant argument.\n");
2459 }
2460
2461 newNode = dpi_call(rtype, fname, argtypes, args);
2462
2463 for (auto arg : args)
2464 delete arg;
2465
2466 goto apply_newNode;
2467 }
2468
2469 if (current_scope.count(str) == 0 || current_scope[str]->type != AST_FUNCTION)
2470 log_file_error(filename, location.first_line, "Can't resolve function name `%s'.\n", str.c_str());
2471 }
2472
2473 if (type == AST_TCALL)
2474 {
2475 if (str == "$finish" || str == "$stop")
2476 {
2477 if (!current_always || current_always->type != AST_INITIAL)
2478 log_file_error(filename, location.first_line, "System task `%s' outside initial block is unsupported.\n", str.c_str());
2479
2480 log_file_error(filename, location.first_line, "System task `%s' executed.\n", str.c_str());
2481 }
2482
2483 if (str == "\\$readmemh" || str == "\\$readmemb")
2484 {
2485 if (GetSize(children) < 2 || GetSize(children) > 4)
2486 log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 2-4.\n",
2487 RTLIL::unescape_id(str).c_str(), int(children.size()));
2488
2489 AstNode *node_filename = children[0]->clone();
2490 while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2491 if (node_filename->type != AST_CONSTANT)
2492 log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str());
2493
2494 AstNode *node_memory = children[1]->clone();
2495 while (node_memory->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2496 if (node_memory->type != AST_IDENTIFIER || node_memory->id2ast == nullptr || node_memory->id2ast->type != AST_MEMORY)
2497 log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str.c_str());
2498
2499 int start_addr = -1, finish_addr = -1;
2500
2501 if (GetSize(children) > 2) {
2502 AstNode *node_addr = children[2]->clone();
2503 while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2504 if (node_addr->type != AST_CONSTANT)
2505 log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str.c_str());
2506 start_addr = int(node_addr->asInt(false));
2507 }
2508
2509 if (GetSize(children) > 3) {
2510 AstNode *node_addr = children[3]->clone();
2511 while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2512 if (node_addr->type != AST_CONSTANT)
2513 log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str.c_str());
2514 finish_addr = int(node_addr->asInt(false));
2515 }
2516
2517 bool unconditional_init = false;
2518 if (current_always->type == AST_INITIAL) {
2519 pool<AstNode*> queue;
2520 log_assert(current_always->children[0]->type == AST_BLOCK);
2521 queue.insert(current_always->children[0]);
2522 while (!unconditional_init && !queue.empty()) {
2523 pool<AstNode*> next_queue;
2524 for (auto n : queue)
2525 for (auto c : n->children) {
2526 if (c == this)
2527 unconditional_init = true;
2528 next_queue.insert(c);
2529 }
2530 next_queue.swap(queue);
2531 }
2532 }
2533
2534 newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init);
2535 delete node_filename;
2536 delete node_memory;
2537 goto apply_newNode;
2538 }
2539
2540 if (current_scope.count(str) == 0 || current_scope[str]->type != AST_TASK)
2541 log_file_error(filename, location.first_line, "Can't resolve task name `%s'.\n", str.c_str());
2542 }
2543
2544 AstNode *decl = current_scope[str];
2545
2546 std::stringstream sstr;
2547 sstr << "$func$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++) << "$";
2548 std::string prefix = sstr.str();
2549
2550 bool recommend_const_eval = false;
2551 bool require_const_eval = in_param ? false : has_const_only_constructs(recommend_const_eval);
2552 if ((in_param || recommend_const_eval || require_const_eval) && !decl->attributes.count("\\via_celltype"))
2553 {
2554 bool all_args_const = true;
2555 for (auto child : children) {
2556 while (child->simplify(true, false, false, 1, -1, false, true)) { }
2557 if (child->type != AST_CONSTANT)
2558 all_args_const = false;
2559 }
2560
2561 if (all_args_const) {
2562 AstNode *func_workspace = current_scope[str]->clone();
2563 newNode = func_workspace->eval_const_function(this);
2564 delete func_workspace;
2565 goto apply_newNode;
2566 }
2567
2568 if (in_param)
2569 log_file_error(filename, location.first_line, "Non-constant function call in constant expression.\n");
2570 if (require_const_eval)
2571 log_file_error(filename, location.first_line, "Function %s can only be called with constant arguments.\n", str.c_str());
2572 }
2573
2574 size_t arg_count = 0;
2575 std::map<std::string, std::string> replace_rules;
2576 vector<AstNode*> added_mod_children;
2577 dict<std::string, AstNode*> wire_cache;
2578 vector<AstNode*> new_stmts;
2579 vector<AstNode*> output_assignments;
2580
2581 if (current_block == NULL)
2582 {
2583 log_assert(type == AST_FCALL);
2584
2585 AstNode *wire = NULL;
2586 for (auto child : decl->children)
2587 if (child->type == AST_WIRE && child->str == str)
2588 wire = child->clone();
2589 log_assert(wire != NULL);
2590
2591 wire->str = prefix + str;
2592 wire->port_id = 0;
2593 wire->is_input = false;
2594 wire->is_output = false;
2595
2596 current_ast_mod->children.push_back(wire);
2597 while (wire->simplify(true, false, false, 1, -1, false, false)) { }
2598
2599 AstNode *lvalue = new AstNode(AST_IDENTIFIER);
2600 lvalue->str = wire->str;
2601
2602 AstNode *always = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK,
2603 new AstNode(AST_ASSIGN_EQ, lvalue, clone())));
2604 always->children[0]->children[0]->was_checked = true;
2605
2606 current_ast_mod->children.push_back(always);
2607
2608 goto replace_fcall_with_id;
2609 }
2610
2611 if (decl->attributes.count("\\via_celltype"))
2612 {
2613 std::string celltype = decl->attributes.at("\\via_celltype")->asAttrConst().decode_string();
2614 std::string outport = str;
2615
2616 if (celltype.find(' ') != std::string::npos) {
2617 int pos = celltype.find(' ');
2618 outport = RTLIL::escape_id(celltype.substr(pos+1));
2619 celltype = RTLIL::escape_id(celltype.substr(0, pos));
2620 } else
2621 celltype = RTLIL::escape_id(celltype);
2622
2623 AstNode *cell = new AstNode(AST_CELL, new AstNode(AST_CELLTYPE));
2624 cell->str = prefix.substr(0, GetSize(prefix)-1);
2625 cell->children[0]->str = celltype;
2626
2627 for (auto attr : decl->attributes)
2628 if (attr.first.str().rfind("\\via_celltype_defparam_", 0) == 0)
2629 {
2630 AstNode *cell_arg = new AstNode(AST_PARASET, attr.second->clone());
2631 cell_arg->str = RTLIL::escape_id(attr.first.substr(strlen("\\via_celltype_defparam_")));
2632 cell->children.push_back(cell_arg);
2633 }
2634
2635 for (auto child : decl->children)
2636 if (child->type == AST_WIRE && (child->is_input || child->is_output || (type == AST_FCALL && child->str == str)))
2637 {
2638 AstNode *wire = child->clone();
2639 wire->str = prefix + wire->str;
2640 wire->port_id = 0;
2641 wire->is_input = false;
2642 wire->is_output = false;
2643 current_ast_mod->children.push_back(wire);
2644 while (wire->simplify(true, false, false, 1, -1, false, false)) { }
2645
2646 AstNode *wire_id = new AstNode(AST_IDENTIFIER);
2647 wire_id->str = wire->str;
2648
2649 if ((child->is_input || child->is_output) && arg_count < children.size())
2650 {
2651 AstNode *arg = children[arg_count++]->clone();
2652 AstNode *assign = child->is_input ?
2653 new AstNode(AST_ASSIGN_EQ, wire_id->clone(), arg) :
2654 new AstNode(AST_ASSIGN_EQ, arg, wire_id->clone());
2655 assign->children[0]->was_checked = true;
2656
2657 for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
2658 if (*it != current_block_child)
2659 continue;
2660 current_block->children.insert(it, assign);
2661 break;
2662 }
2663 }
2664
2665 AstNode *cell_arg = new AstNode(AST_ARGUMENT, wire_id);
2666 cell_arg->str = child->str == str ? outport : child->str;
2667 cell->children.push_back(cell_arg);
2668 }
2669
2670 current_ast_mod->children.push_back(cell);
2671 goto replace_fcall_with_id;
2672 }
2673
2674 for (auto child : decl->children)
2675 if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_ENUM_ITEM)
2676 {
2677 AstNode *wire = nullptr;
2678
2679 if (wire_cache.count(child->str))
2680 {
2681 wire = wire_cache.at(child->str);
2682 if (wire->children.empty()) {
2683 for (auto c : child->children)
2684 wire->children.push_back(c->clone());
2685 } else if (!child->children.empty()) {
2686 while (child->simplify(true, false, false, stage, -1, false, false)) { }
2687 if (GetSize(child->children) == GetSize(wire->children)) {
2688 for (int i = 0; i < GetSize(child->children); i++)
2689 if (*child->children.at(i) != *wire->children.at(i))
2690 goto tcall_incompatible_wires;
2691 } else {
2692 tcall_incompatible_wires:
2693 log_file_error(filename, location.first_line, "Incompatible re-declaration of wire %s.\n", child->str.c_str());
2694 }
2695 }
2696 }
2697 else
2698 {
2699 wire = child->clone();
2700 wire->str = prefix + wire->str;
2701 wire->port_id = 0;
2702 wire->is_input = false;
2703 wire->is_output = false;
2704 wire->is_reg = true;
2705 wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
2706 if (child->type == AST_ENUM_ITEM)
2707 wire->attributes["\\enum_base_type"] = child->attributes["\\enum_base_type"];
2708
2709 wire_cache[child->str] = wire;
2710
2711 current_ast_mod->children.push_back(wire);
2712 added_mod_children.push_back(wire);
2713 }
2714
2715 if (child->type == AST_WIRE)
2716 while (wire->simplify(true, false, false, 1, -1, false, false)) { }
2717
2718 replace_rules[child->str] = wire->str;
2719 current_scope[wire->str] = wire;
2720
2721 if ((child->is_input || child->is_output) && arg_count < children.size())
2722 {
2723 AstNode *arg = children[arg_count++]->clone();
2724 AstNode *wire_id = new AstNode(AST_IDENTIFIER);
2725 wire_id->str = wire->str;
2726 AstNode *assign = child->is_input ?
2727 new AstNode(AST_ASSIGN_EQ, wire_id, arg) :
2728 new AstNode(AST_ASSIGN_EQ, arg, wire_id);
2729 assign->children[0]->was_checked = true;
2730 if (child->is_input)
2731 new_stmts.push_back(assign);
2732 else
2733 output_assignments.push_back(assign);
2734 }
2735 }
2736
2737 for (auto child : added_mod_children) {
2738 child->replace_ids(prefix, replace_rules);
2739 while (child->simplify(true, false, false, 1, -1, false, false)) { }
2740 }
2741
2742 for (auto child : decl->children)
2743 if (child->type != AST_WIRE && child->type != AST_MEMORY && child->type != AST_PARAMETER && child->type != AST_LOCALPARAM)
2744 {
2745 AstNode *stmt = child->clone();
2746 stmt->replace_ids(prefix, replace_rules);
2747 new_stmts.push_back(stmt);
2748 }
2749
2750 new_stmts.insert(new_stmts.end(), output_assignments.begin(), output_assignments.end());
2751
2752 for (auto it = current_block->children.begin(); ; it++) {
2753 log_assert(it != current_block->children.end());
2754 if (*it == current_block_child) {
2755 current_block->children.insert(it, new_stmts.begin(), new_stmts.end());
2756 break;
2757 }
2758 }
2759
2760 replace_fcall_with_id:
2761 if (type == AST_FCALL) {
2762 delete_children();
2763 type = AST_IDENTIFIER;
2764 str = prefix + str;
2765 }
2766 if (type == AST_TCALL)
2767 str = "";
2768 did_something = true;
2769 }
2770
2771 replace_fcall_later:;
2772
2773 // perform const folding when activated
2774 if (const_fold)
2775 {
2776 bool string_op;
2777 std::vector<RTLIL::State> tmp_bits;
2778 RTLIL::Const (*const_func)(const RTLIL::Const&, const RTLIL::Const&, bool, bool, int);
2779 RTLIL::Const dummy_arg;
2780
2781 switch (type)
2782 {
2783 case AST_IDENTIFIER:
2784 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)) {
2785 if (current_scope[str]->children[0]->type == AST_CONSTANT) {
2786 if (children.size() != 0 && children[0]->type == AST_RANGE && children[0]->range_valid) {
2787 std::vector<RTLIL::State> data;
2788 bool param_upto = current_scope[str]->range_valid && current_scope[str]->range_swapped;
2789 int param_offset = current_scope[str]->range_valid ? current_scope[str]->range_right : 0;
2790 int param_width = current_scope[str]->range_valid ? current_scope[str]->range_left - current_scope[str]->range_right + 1 :
2791 GetSize(current_scope[str]->children[0]->bits);
2792 int tmp_range_left = children[0]->range_left, tmp_range_right = children[0]->range_right;
2793 if (param_upto) {
2794 tmp_range_left = (param_width + 2*param_offset) - children[0]->range_right - 1;
2795 tmp_range_right = (param_width + 2*param_offset) - children[0]->range_left - 1;
2796 }
2797 for (int i = tmp_range_right; i <= tmp_range_left; i++) {
2798 int index = i - param_offset;
2799 if (0 <= index && index < param_width)
2800 data.push_back(current_scope[str]->children[0]->bits[index]);
2801 else
2802 data.push_back(RTLIL::State::Sx);
2803 }
2804 newNode = mkconst_bits(data, false);
2805 } else
2806 if (children.size() == 0)
2807 newNode = current_scope[str]->children[0]->clone();
2808 } else
2809 if (current_scope[str]->children[0]->isConst())
2810 newNode = current_scope[str]->children[0]->clone();
2811 }
2812 else if (at_zero && current_scope.count(str) > 0 && (current_scope[str]->type == AST_WIRE || current_scope[str]->type == AST_AUTOWIRE)) {
2813 newNode = mkconst_int(0, sign_hint, width_hint);
2814 }
2815 break;
2816 case AST_BIT_NOT:
2817 if (children[0]->type == AST_CONSTANT) {
2818 RTLIL::Const y = RTLIL::const_not(children[0]->bitsAsConst(width_hint, sign_hint), dummy_arg, sign_hint, false, width_hint);
2819 newNode = mkconst_bits(y.bits, sign_hint);
2820 }
2821 break;
2822 case AST_TO_SIGNED:
2823 case AST_TO_UNSIGNED:
2824 if (children[0]->type == AST_CONSTANT) {
2825 RTLIL::Const y = children[0]->bitsAsConst(width_hint, sign_hint);
2826 newNode = mkconst_bits(y.bits, type == AST_TO_SIGNED);
2827 }
2828 break;
2829 if (0) { case AST_BIT_AND: const_func = RTLIL::const_and; }
2830 if (0) { case AST_BIT_OR: const_func = RTLIL::const_or; }
2831 if (0) { case AST_BIT_XOR: const_func = RTLIL::const_xor; }
2832 if (0) { case AST_BIT_XNOR: const_func = RTLIL::const_xnor; }
2833 if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
2834 RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
2835 children[1]->bitsAsConst(width_hint, sign_hint), sign_hint, sign_hint, width_hint);
2836 newNode = mkconst_bits(y.bits, sign_hint);
2837 }
2838 break;
2839 if (0) { case AST_REDUCE_AND: const_func = RTLIL::const_reduce_and; }
2840 if (0) { case AST_REDUCE_OR: const_func = RTLIL::const_reduce_or; }
2841 if (0) { case AST_REDUCE_XOR: const_func = RTLIL::const_reduce_xor; }
2842 if (0) { case AST_REDUCE_XNOR: const_func = RTLIL::const_reduce_xnor; }
2843 if (0) { case AST_REDUCE_BOOL: const_func = RTLIL::const_reduce_bool; }
2844 if (children[0]->type == AST_CONSTANT) {
2845 RTLIL::Const y = const_func(RTLIL::Const(children[0]->bits), dummy_arg, false, false, -1);
2846 newNode = mkconst_bits(y.bits, false);
2847 }
2848 break;
2849 case AST_LOGIC_NOT:
2850 if (children[0]->type == AST_CONSTANT) {
2851 RTLIL::Const y = RTLIL::const_logic_not(RTLIL::Const(children[0]->bits), dummy_arg, children[0]->is_signed, false, -1);
2852 newNode = mkconst_bits(y.bits, false);
2853 } else
2854 if (children[0]->isConst()) {
2855 newNode = mkconst_int(children[0]->asReal(sign_hint) == 0, false, 1);
2856 }
2857 break;
2858 if (0) { case AST_LOGIC_AND: const_func = RTLIL::const_logic_and; }
2859 if (0) { case AST_LOGIC_OR: const_func = RTLIL::const_logic_or; }
2860 if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
2861 RTLIL::Const y = const_func(RTLIL::Const(children[0]->bits), RTLIL::Const(children[1]->bits),
2862 children[0]->is_signed, children[1]->is_signed, -1);
2863 newNode = mkconst_bits(y.bits, false);
2864 } else
2865 if (children[0]->isConst() && children[1]->isConst()) {
2866 if (type == AST_LOGIC_AND)
2867 newNode = mkconst_int((children[0]->asReal(sign_hint) != 0) && (children[1]->asReal(sign_hint) != 0), false, 1);
2868 else
2869 newNode = mkconst_int((children[0]->asReal(sign_hint) != 0) || (children[1]->asReal(sign_hint) != 0), false, 1);
2870 }
2871 break;
2872 if (0) { case AST_SHIFT_LEFT: const_func = RTLIL::const_shl; }
2873 if (0) { case AST_SHIFT_RIGHT: const_func = RTLIL::const_shr; }
2874 if (0) { case AST_SHIFT_SLEFT: const_func = RTLIL::const_sshl; }
2875 if (0) { case AST_SHIFT_SRIGHT: const_func = RTLIL::const_sshr; }
2876 if (0) { case AST_POW: const_func = RTLIL::const_pow; }
2877 if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
2878 RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
2879 RTLIL::Const(children[1]->bits), sign_hint, type == AST_POW ? children[1]->is_signed : false, width_hint);
2880 newNode = mkconst_bits(y.bits, sign_hint);
2881 } else
2882 if (type == AST_POW && children[0]->isConst() && children[1]->isConst()) {
2883 newNode = new AstNode(AST_REALVALUE);
2884 newNode->realvalue = pow(children[0]->asReal(sign_hint), children[1]->asReal(sign_hint));
2885 }
2886 break;
2887 if (0) { case AST_LT: const_func = RTLIL::const_lt; }
2888 if (0) { case AST_LE: const_func = RTLIL::const_le; }
2889 if (0) { case AST_EQ: const_func = RTLIL::const_eq; }
2890 if (0) { case AST_NE: const_func = RTLIL::const_ne; }
2891 if (0) { case AST_EQX: const_func = RTLIL::const_eqx; }
2892 if (0) { case AST_NEX: const_func = RTLIL::const_nex; }
2893 if (0) { case AST_GE: const_func = RTLIL::const_ge; }
2894 if (0) { case AST_GT: const_func = RTLIL::const_gt; }
2895 if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
2896 int cmp_width = max(children[0]->bits.size(), children[1]->bits.size());
2897 bool cmp_signed = children[0]->is_signed && children[1]->is_signed;
2898 RTLIL::Const y = const_func(children[0]->bitsAsConst(cmp_width, cmp_signed),
2899 children[1]->bitsAsConst(cmp_width, cmp_signed), cmp_signed, cmp_signed, 1);
2900 newNode = mkconst_bits(y.bits, false);
2901 } else
2902 if (children[0]->isConst() && children[1]->isConst()) {
2903 bool cmp_signed = (children[0]->type == AST_REALVALUE || children[0]->is_signed) && (children[1]->type == AST_REALVALUE || children[1]->is_signed);
2904 switch (type) {
2905 case AST_LT: newNode = mkconst_int(children[0]->asReal(cmp_signed) < children[1]->asReal(cmp_signed), false, 1); break;
2906 case AST_LE: newNode = mkconst_int(children[0]->asReal(cmp_signed) <= children[1]->asReal(cmp_signed), false, 1); break;
2907 case AST_EQ: newNode = mkconst_int(children[0]->asReal(cmp_signed) == children[1]->asReal(cmp_signed), false, 1); break;
2908 case AST_NE: newNode = mkconst_int(children[0]->asReal(cmp_signed) != children[1]->asReal(cmp_signed), false, 1); break;
2909 case AST_EQX: newNode = mkconst_int(children[0]->asReal(cmp_signed) == children[1]->asReal(cmp_signed), false, 1); break;
2910 case AST_NEX: newNode = mkconst_int(children[0]->asReal(cmp_signed) != children[1]->asReal(cmp_signed), false, 1); break;
2911 case AST_GE: newNode = mkconst_int(children[0]->asReal(cmp_signed) >= children[1]->asReal(cmp_signed), false, 1); break;
2912 case AST_GT: newNode = mkconst_int(children[0]->asReal(cmp_signed) > children[1]->asReal(cmp_signed), false, 1); break;
2913 default: log_abort();
2914 }
2915 }
2916 break;
2917 if (0) { case AST_ADD: const_func = RTLIL::const_add; }
2918 if (0) { case AST_SUB: const_func = RTLIL::const_sub; }
2919 if (0) { case AST_MUL: const_func = RTLIL::const_mul; }
2920 if (0) { case AST_DIV: const_func = RTLIL::const_div; }
2921 if (0) { case AST_MOD: const_func = RTLIL::const_mod; }
2922 if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
2923 RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
2924 children[1]->bitsAsConst(width_hint, sign_hint), sign_hint, sign_hint, width_hint);
2925 newNode = mkconst_bits(y.bits, sign_hint);
2926 } else
2927 if (children[0]->isConst() && children[1]->isConst()) {
2928 newNode = new AstNode(AST_REALVALUE);
2929 switch (type) {
2930 case AST_ADD: newNode->realvalue = children[0]->asReal(sign_hint) + children[1]->asReal(sign_hint); break;
2931 case AST_SUB: newNode->realvalue = children[0]->asReal(sign_hint) - children[1]->asReal(sign_hint); break;
2932 case AST_MUL: newNode->realvalue = children[0]->asReal(sign_hint) * children[1]->asReal(sign_hint); break;
2933 case AST_DIV: newNode->realvalue = children[0]->asReal(sign_hint) / children[1]->asReal(sign_hint); break;
2934 case AST_MOD: newNode->realvalue = fmod(children[0]->asReal(sign_hint), children[1]->asReal(sign_hint)); break;
2935 default: log_abort();
2936 }
2937 }
2938 break;
2939 if (0) { case AST_POS: const_func = RTLIL::const_pos; }
2940 if (0) { case AST_NEG: const_func = RTLIL::const_neg; }
2941 if (children[0]->type == AST_CONSTANT) {
2942 RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint), dummy_arg, sign_hint, false, width_hint);
2943 newNode = mkconst_bits(y.bits, sign_hint);
2944 } else
2945 if (children[0]->isConst()) {
2946 newNode = new AstNode(AST_REALVALUE);
2947 if (type == AST_POS)
2948 newNode->realvalue = +children[0]->asReal(sign_hint);
2949 else
2950 newNode->realvalue = -children[0]->asReal(sign_hint);
2951 }
2952 break;
2953 case AST_TERNARY:
2954 if (children[0]->isConst())
2955 {
2956 bool found_sure_true = false;
2957 bool found_maybe_true = false;
2958
2959 if (children[0]->type == AST_CONSTANT)
2960 for (auto &bit : children[0]->bits) {
2961 if (bit == RTLIL::State::S1)
2962 found_sure_true = true;
2963 if (bit > RTLIL::State::S1)
2964 found_maybe_true = true;
2965 }
2966 else
2967 found_sure_true = children[0]->asReal(sign_hint) != 0;
2968
2969 AstNode *choice = NULL, *not_choice = NULL;
2970 if (found_sure_true)
2971 choice = children[1], not_choice = children[2];
2972 else if (!found_maybe_true)
2973 choice = children[2], not_choice = children[1];
2974
2975 if (choice != NULL) {
2976 if (choice->type == AST_CONSTANT) {
2977 int other_width_hint = width_hint;
2978 bool other_sign_hint = sign_hint, other_real = false;
2979 not_choice->detectSignWidth(other_width_hint, other_sign_hint, &other_real);
2980 if (other_real) {
2981 newNode = new AstNode(AST_REALVALUE);
2982 choice->detectSignWidth(width_hint, sign_hint);
2983 newNode->realvalue = choice->asReal(sign_hint);
2984 } else {
2985 RTLIL::Const y = choice->bitsAsConst(width_hint, sign_hint);
2986 if (choice->is_string && y.bits.size() % 8 == 0 && sign_hint == false)
2987 newNode = mkconst_str(y.bits);
2988 else
2989 newNode = mkconst_bits(y.bits, sign_hint);
2990 }
2991 } else
2992 if (choice->isConst()) {
2993 newNode = choice->clone();
2994 }
2995 } else if (children[1]->type == AST_CONSTANT && children[2]->type == AST_CONSTANT) {
2996 RTLIL::Const a = children[1]->bitsAsConst(width_hint, sign_hint);
2997 RTLIL::Const b = children[2]->bitsAsConst(width_hint, sign_hint);
2998 log_assert(a.bits.size() == b.bits.size());
2999 for (size_t i = 0; i < a.bits.size(); i++)
3000 if (a.bits[i] != b.bits[i])
3001 a.bits[i] = RTLIL::State::Sx;
3002 newNode = mkconst_bits(a.bits, sign_hint);
3003 } else if (children[1]->isConst() && children[2]->isConst()) {
3004 newNode = new AstNode(AST_REALVALUE);
3005 if (children[1]->asReal(sign_hint) == children[2]->asReal(sign_hint))
3006 newNode->realvalue = children[1]->asReal(sign_hint);
3007 else
3008 // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
3009 // the data type in question should be returned if the ?: is ambiguous. The
3010 // value in Table 7-1 for the 'real' type is 0.0.
3011 newNode->realvalue = 0.0;
3012 }
3013 }
3014 break;
3015 case AST_CONCAT:
3016 string_op = !children.empty();
3017 for (auto it = children.begin(); it != children.end(); it++) {
3018 if ((*it)->type != AST_CONSTANT)
3019 goto not_const;
3020 if (!(*it)->is_string)
3021 string_op = false;
3022 tmp_bits.insert(tmp_bits.end(), (*it)->bits.begin(), (*it)->bits.end());
3023 }
3024 newNode = string_op ? mkconst_str(tmp_bits) : mkconst_bits(tmp_bits, false);
3025 break;
3026 case AST_REPLICATE:
3027 if (children.at(0)->type != AST_CONSTANT || children.at(1)->type != AST_CONSTANT)
3028 goto not_const;
3029 for (int i = 0; i < children[0]->bitsAsConst().as_int(); i++)
3030 tmp_bits.insert(tmp_bits.end(), children.at(1)->bits.begin(), children.at(1)->bits.end());
3031 newNode = children.at(1)->is_string ? mkconst_str(tmp_bits) : mkconst_bits(tmp_bits, false);
3032 break;
3033 default:
3034 not_const:
3035 break;
3036 }
3037 }
3038
3039 // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
3040 if (newNode) {
3041 apply_newNode:
3042 // fprintf(stderr, "----\n");
3043 // dumpAst(stderr, "- ");
3044 // newNode->dumpAst(stderr, "+ ");
3045 log_assert(newNode != NULL);
3046 newNode->filename = filename;
3047 newNode->location = location;
3048 newNode->cloneInto(this);
3049 delete newNode;
3050 did_something = true;
3051 }
3052
3053 if (!did_something)
3054 basic_prep = true;
3055
3056 recursion_counter--;
3057 return did_something;
3058 }
3059
3060 static void replace_result_wire_name_in_function(AstNode *node, std::string &from, std::string &to)
3061 {
3062 for (auto &it : node->children)
3063 replace_result_wire_name_in_function(it, from, to);
3064 if (node->str == from)
3065 node->str = to;
3066 }
3067
3068 // replace a readmem[bh] TCALL ast node with a block of memory assignments
3069 AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init)
3070 {
3071 int mem_width, mem_size, addr_bits;
3072 memory->meminfo(mem_width, mem_size, addr_bits);
3073
3074 AstNode *block = new AstNode(AST_BLOCK);
3075
3076 AstNode *meminit = nullptr;
3077 int next_meminit_cursor=0;
3078 vector<State> meminit_bits;
3079 int meminit_size=0;
3080
3081 std::ifstream f;
3082 f.open(mem_filename.c_str());
3083 if (f.fail()) {
3084 #ifdef _WIN32
3085 char slash = '\\';
3086 #else
3087 char slash = '/';
3088 #endif
3089 std::string path = filename.substr(0, filename.find_last_of(slash)+1);
3090 f.open(path + mem_filename.c_str());
3091 yosys_input_files.insert(path + mem_filename);
3092 } else {
3093 yosys_input_files.insert(mem_filename);
3094 }
3095 if (f.fail() || GetSize(mem_filename) == 0)
3096 log_file_error(filename, location.first_line, "Can not open file `%s` for %s.\n", mem_filename.c_str(), str.c_str());
3097
3098 log_assert(GetSize(memory->children) == 2 && memory->children[1]->type == AST_RANGE && memory->children[1]->range_valid);
3099 int range_left = memory->children[1]->range_left, range_right = memory->children[1]->range_right;
3100 int range_min = min(range_left, range_right), range_max = max(range_left, range_right);
3101
3102 if (start_addr < 0)
3103 start_addr = range_min;
3104
3105 if (finish_addr < 0)
3106 finish_addr = range_max + 1;
3107
3108 bool in_comment = false;
3109 int increment = start_addr <= finish_addr ? +1 : -1;
3110 int cursor = start_addr;
3111
3112 while (!f.eof())
3113 {
3114 std::string line, token;
3115 std::getline(f, line);
3116
3117 for (int i = 0; i < GetSize(line); i++) {
3118 if (in_comment && line.compare(i, 2, "*/") == 0) {
3119 line[i] = ' ';
3120 line[i+1] = ' ';
3121 in_comment = false;
3122 continue;
3123 }
3124 if (!in_comment && line.compare(i, 2, "/*") == 0)
3125 in_comment = true;
3126 if (in_comment)
3127 line[i] = ' ';
3128 }
3129
3130 while (1)
3131 {
3132 token = next_token(line, " \t\r\n");
3133 if (token.empty() || token.compare(0, 2, "//") == 0)
3134 break;
3135
3136 if (token[0] == '@') {
3137 token = token.substr(1);
3138 const char *nptr = token.c_str();
3139 char *endptr;
3140 cursor = strtol(nptr, &endptr, 16);
3141 if (!*nptr || *endptr)
3142 log_file_error(filename, location.first_line, "Can not parse address `%s` for %s.\n", nptr, str.c_str());
3143 continue;
3144 }
3145
3146 AstNode *value = VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width, is_readmemh ? 'h' : 'b') + token);
3147
3148 if (unconditional_init)
3149 {
3150 if (meminit == nullptr || cursor != next_meminit_cursor)
3151 {
3152 if (meminit != nullptr) {
3153 meminit->children[1] = AstNode::mkconst_bits(meminit_bits, false);
3154 meminit->children[2] = AstNode::mkconst_int(meminit_size, false);
3155 }
3156
3157 meminit = new AstNode(AST_MEMINIT);
3158 meminit->children.push_back(AstNode::mkconst_int(cursor, false));
3159 meminit->children.push_back(nullptr);
3160 meminit->children.push_back(nullptr);
3161 meminit->str = memory->str;
3162 meminit->id2ast = memory;
3163 meminit_bits.clear();
3164 meminit_size = 0;
3165
3166 current_ast_mod->children.push_back(meminit);
3167 next_meminit_cursor = cursor;
3168 }
3169
3170 meminit_size++;
3171 next_meminit_cursor++;
3172 meminit_bits.insert(meminit_bits.end(), value->bits.begin(), value->bits.end());
3173 delete value;
3174 }
3175 else
3176 {
3177 block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor, false))), value));
3178 block->children.back()->children[0]->str = memory->str;
3179 block->children.back()->children[0]->id2ast = memory;
3180 block->children.back()->children[0]->was_checked = true;
3181 }
3182
3183 cursor += increment;
3184 if ((cursor == finish_addr+increment) || (increment > 0 && cursor > range_max) || (increment < 0 && cursor < range_min))
3185 break;
3186 }
3187
3188 if ((cursor == finish_addr+increment) || (increment > 0 && cursor > range_max) || (increment < 0 && cursor < range_min))
3189 break;
3190 }
3191
3192 if (meminit != nullptr) {
3193 meminit->children[1] = AstNode::mkconst_bits(meminit_bits, false);
3194 meminit->children[2] = AstNode::mkconst_int(meminit_size, false);
3195 }
3196
3197 return block;
3198 }
3199
3200 // annotate the names of all wires and other named objects in a generate block
3201 void AstNode::expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map)
3202 {
3203 if (!index_var.empty() && type == AST_IDENTIFIER && str == index_var) {
3204 if (children.empty()) {
3205 current_scope[index_var]->children[0]->cloneInto(this);
3206 } else {
3207 AstNode *p = new AstNode(AST_LOCALPARAM, current_scope[index_var]->children[0]->clone());
3208 p->str = stringf("$genval$%d", autoidx++);
3209 current_ast_mod->children.push_back(p);
3210 str = p->str;
3211 id2ast = p;
3212 }
3213 }
3214
3215 if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE) && name_map.count(str) > 0)
3216 str = name_map[str];
3217
3218 std::map<std::string, std::string> backup_name_map;
3219
3220 for (size_t i = 0; i < children.size(); i++) {
3221 AstNode *child = children[i];
3222 if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM ||
3223 child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF || child->type == AST_ENUM_ITEM) {
3224 if (backup_name_map.size() == 0)
3225 backup_name_map = name_map;
3226 std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
3227 size_t pos = child->str.rfind('.');
3228 if (pos == std::string::npos)
3229 pos = child->str[0] == '\\' && prefix[0] == '\\' ? 1 : 0;
3230 else
3231 pos = pos + 1;
3232 new_name = child->str.substr(0, pos) + new_name + child->str.substr(pos);
3233 if (new_name[0] != '$' && new_name[0] != '\\')
3234 new_name = prefix[0] + new_name;
3235 name_map[child->str] = new_name;
3236 if (child->type == AST_FUNCTION)
3237 replace_result_wire_name_in_function(child, child->str, new_name);
3238 else
3239 child->str = new_name;
3240 current_scope[new_name] = child;
3241 }
3242 if (child->type == AST_ENUM){
3243 current_scope[child->str] = child;
3244 for (auto enode : child->children){
3245 log_assert(enode->type == AST_ENUM_ITEM);
3246 if (backup_name_map.size() == 0)
3247 backup_name_map = name_map;
3248 std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
3249 size_t pos = enode->str.rfind('.');
3250 if (pos == std::string::npos)
3251 pos = enode->str[0] == '\\' && prefix[0] == '\\' ? 1 : 0;
3252 else
3253 pos = pos + 1;
3254 new_name = enode->str.substr(0, pos) + new_name + enode->str.substr(pos);
3255 if (new_name[0] != '$' && new_name[0] != '\\')
3256 new_name = prefix[0] + new_name;
3257 name_map[enode->str] = new_name;
3258
3259 enode->str = new_name;
3260 current_scope[new_name] = enode;
3261 }
3262 }
3263 }
3264
3265 for (size_t i = 0; i < children.size(); i++) {
3266 AstNode *child = children[i];
3267 // AST_PREFIX member names should not be prefixed; a nested AST_PREFIX
3268 // still needs to recursed-into
3269 if (type == AST_PREFIX && i == 1 && child->type == AST_IDENTIFIER)
3270 continue;
3271 if (child->type != AST_FUNCTION && child->type != AST_TASK)
3272 child->expand_genblock(index_var, prefix, name_map);
3273 }
3274
3275
3276 if (backup_name_map.size() > 0)
3277 name_map.swap(backup_name_map);
3278 }
3279
3280 // rename stuff (used when tasks of functions are instantiated)
3281 void AstNode::replace_ids(const std::string &prefix, const std::map<std::string, std::string> &rules)
3282 {
3283 if (type == AST_BLOCK)
3284 {
3285 std::map<std::string, std::string> new_rules = rules;
3286 std::string new_prefix = prefix + str;
3287
3288 for (auto child : children)
3289 if (child->type == AST_WIRE) {
3290 new_rules[child->str] = new_prefix + child->str;
3291 child->str = new_prefix + child->str;
3292 }
3293
3294 for (auto child : children)
3295 if (child->type != AST_WIRE)
3296 child->replace_ids(new_prefix, new_rules);
3297 }
3298 else
3299 {
3300 if (type == AST_IDENTIFIER && rules.count(str) > 0)
3301 str = rules.at(str);
3302 for (auto child : children)
3303 child->replace_ids(prefix, rules);
3304 }
3305 }
3306
3307 // helper function for mem2reg_as_needed_pass1
3308 static void mark_memories_assign_lhs_complex(dict<AstNode*, pool<std::string>> &mem2reg_places,
3309 dict<AstNode*, uint32_t> &mem2reg_candidates, AstNode *that)
3310 {
3311 for (auto &child : that->children)
3312 mark_memories_assign_lhs_complex(mem2reg_places, mem2reg_candidates, child);
3313
3314 if (that->type == AST_IDENTIFIER && that->id2ast && that->id2ast->type == AST_MEMORY) {
3315 AstNode *mem = that->id2ast;
3316 if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_CMPLX_LHS))
3317 mem2reg_places[mem].insert(stringf("%s:%d", that->filename.c_str(), that->location.first_line));
3318 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CMPLX_LHS;
3319 }
3320 }
3321
3322 // find memories that should be replaced by registers
3323 void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg_places,
3324 dict<AstNode*, uint32_t> &mem2reg_candidates, dict<AstNode*, uint32_t> &proc_flags, uint32_t &flags)
3325 {
3326 uint32_t children_flags = 0;
3327 int lhs_children_counter = 0;
3328
3329 if (type == AST_TYPEDEF)
3330 return; // don't touch content of typedefs
3331
3332 if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ)
3333 {
3334 // mark all memories that are used in a complex expression on the left side of an assignment
3335 for (auto &lhs_child : children[0]->children)
3336 mark_memories_assign_lhs_complex(mem2reg_places, mem2reg_candidates, lhs_child);
3337
3338 if (children[0]->type == AST_IDENTIFIER && children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY)
3339 {
3340 AstNode *mem = children[0]->id2ast;
3341
3342 // activate mem2reg if this is assigned in an async proc
3343 if (flags & AstNode::MEM2REG_FL_ASYNC) {
3344 if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ASYNC))
3345 mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line));
3346 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ASYNC;
3347 }
3348
3349 // remember if this is assigned blocking (=)
3350 if (type == AST_ASSIGN_EQ) {
3351 if (!(proc_flags[mem] & AstNode::MEM2REG_FL_EQ1))
3352 mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line));
3353 proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1;
3354 }
3355
3356 // for proper (non-init) writes: remember if this is a constant index or not
3357 if ((flags & MEM2REG_FL_INIT) == 0) {
3358 if (children[0]->children.size() && children[0]->children[0]->type == AST_RANGE && children[0]->children[0]->children.size()) {
3359 if (children[0]->children[0]->children[0]->type == AST_CONSTANT)
3360 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CONST_LHS;
3361 else
3362 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_VAR_LHS;
3363 }
3364 }
3365
3366 // remember where this is
3367 if (flags & MEM2REG_FL_INIT) {
3368 if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT))
3369 mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line));
3370 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_INIT;
3371 } else {
3372 if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ELSE))
3373 mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line));
3374 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ELSE;
3375 }
3376 }
3377
3378 lhs_children_counter = 1;
3379 }
3380
3381 if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY)
3382 {
3383 AstNode *mem = id2ast;
3384
3385 // flag if used after blocking assignment (in same proc)
3386 if ((proc_flags[mem] & AstNode::MEM2REG_FL_EQ1) && !(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_EQ2)) {
3387 mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), location.first_line));
3388 mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_EQ2;
3389 }
3390 }
3391
3392 // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg'
3393 if (type == AST_MEMORY && (get_bool_attribute(ID::mem2reg) || (flags & AstNode::MEM2REG_FL_ALL) || !is_reg))
3394 mem2reg_candidates[this] |= AstNode::MEM2REG_FL_FORCED;
3395
3396 if (type == AST_MODULE && get_bool_attribute(ID::mem2reg))
3397 children_flags |= AstNode::MEM2REG_FL_ALL;
3398
3399 dict<AstNode*, uint32_t> *proc_flags_p = NULL;
3400
3401 if (type == AST_ALWAYS) {
3402 int count_edge_events = 0;
3403 for (auto child : children)
3404 if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE)
3405 count_edge_events++;
3406 if (count_edge_events != 1)
3407 children_flags |= AstNode::MEM2REG_FL_ASYNC;
3408 proc_flags_p = new dict<AstNode*, uint32_t>;
3409 }
3410
3411 if (type == AST_INITIAL) {
3412 children_flags |= AstNode::MEM2REG_FL_INIT;
3413 proc_flags_p = new dict<AstNode*, uint32_t>;
3414 }
3415
3416 uint32_t backup_flags = flags;
3417 flags |= children_flags;
3418 log_assert((flags & ~0x000000ff) == 0);
3419
3420 for (auto child : children)
3421 {
3422 if (lhs_children_counter > 0) {
3423 lhs_children_counter--;
3424 if (child->children.size() && child->children[0]->type == AST_RANGE && child->children[0]->children.size()) {
3425 for (auto c : child->children[0]->children) {
3426 if (proc_flags_p)
3427 c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags);
3428 else
3429 c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags);
3430 }
3431 }
3432 } else
3433 if (proc_flags_p)
3434 child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags);
3435 else
3436 child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags);
3437 }
3438
3439 flags &= ~children_flags | backup_flags;
3440
3441 if (proc_flags_p) {
3442 #ifndef NDEBUG
3443 for (auto it : *proc_flags_p)
3444 log_assert((it.second & ~0xff000000) == 0);
3445 #endif
3446 delete proc_flags_p;
3447 }
3448 }
3449
3450 bool AstNode::mem2reg_check(pool<AstNode*> &mem2reg_set)
3451 {
3452 if (type != AST_IDENTIFIER || !id2ast || !mem2reg_set.count(id2ast))
3453 return false;
3454
3455 if (children.empty() || children[0]->type != AST_RANGE || GetSize(children[0]->children) != 1)
3456 log_file_error(filename, location.first_line, "Invalid array access.\n");
3457
3458 return true;
3459 }
3460
3461 void AstNode::mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes)
3462 {
3463 log_assert(mem2reg_set.count(this) == 0);
3464
3465 if (mem2reg_set.count(id2ast))
3466 id2ast = nullptr;
3467
3468 for (size_t i = 0; i < children.size(); i++) {
3469 if (mem2reg_set.count(children[i]) > 0) {
3470 delnodes.push_back(children[i]);
3471 children.erase(children.begin() + (i--));
3472 } else {
3473 children[i]->mem2reg_remove(mem2reg_set, delnodes);
3474 }
3475 }
3476 }
3477
3478 // actually replace memories with registers
3479 bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block, AstNode *&async_block)
3480 {
3481 bool did_something = false;
3482
3483 if (type == AST_BLOCK)
3484 block = this;
3485
3486 if (type == AST_FUNCTION || type == AST_TASK)
3487 return false;
3488
3489 if (type == AST_TYPEDEF)
3490 return false;
3491
3492 if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast))
3493 {
3494 log_assert(children[0]->type == AST_CONSTANT);
3495 log_assert(children[1]->type == AST_CONSTANT);
3496 log_assert(children[2]->type == AST_CONSTANT);
3497
3498 int cursor = children[0]->asInt(false);
3499 Const data = children[1]->bitsAsConst();
3500 int length = children[2]->asInt(false);
3501
3502 if (length != 0)
3503 {
3504 AstNode *block = new AstNode(AST_INITIAL, new AstNode(AST_BLOCK));
3505 mod->children.push_back(block);
3506 block = block->children[0];
3507
3508 int wordsz = GetSize(data) / length;
3509
3510 for (int i = 0; i < length; i++) {
3511 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)));
3512 block->children.back()->children[0]->str = str;
3513 block->children.back()->children[0]->id2ast = id2ast;
3514 block->children.back()->children[0]->was_checked = true;
3515 }
3516 }
3517
3518 AstNode *newNode = new AstNode(AST_NONE);
3519 newNode->cloneInto(this);
3520 delete newNode;
3521
3522 did_something = true;
3523 }
3524
3525 if (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set))
3526 {
3527 if (async_block == NULL) {
3528 async_block = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK));
3529 mod->children.push_back(async_block);
3530 }
3531
3532 AstNode *newNode = clone();
3533 newNode->type = AST_ASSIGN_EQ;
3534 newNode->children[0]->was_checked = true;
3535 async_block->children[0]->children.push_back(newNode);
3536
3537 newNode = new AstNode(AST_NONE);
3538 newNode->cloneInto(this);
3539 delete newNode;
3540
3541 did_something = true;
3542 }
3543
3544 if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->mem2reg_check(mem2reg_set) &&
3545 children[0]->children[0]->children[0]->type != AST_CONSTANT)
3546 {
3547 std::stringstream sstr;
3548 sstr << "$mem2reg_wr$" << children[0]->str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
3549 std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
3550
3551 int mem_width, mem_size, addr_bits;
3552 bool mem_signed = children[0]->id2ast->is_signed;
3553 children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
3554
3555 AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
3556 wire_addr->str = id_addr;
3557 wire_addr->is_reg = true;
3558 wire_addr->was_checked = true;
3559 wire_addr->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
3560 mod->children.push_back(wire_addr);
3561 while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
3562
3563 AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
3564 wire_data->str = id_data;
3565 wire_data->is_reg = true;
3566 wire_data->was_checked = true;
3567 wire_data->is_signed = mem_signed;
3568 wire_data->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
3569 mod->children.push_back(wire_data);
3570 while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
3571
3572 log_assert(block != NULL);
3573 size_t assign_idx = 0;
3574 while (assign_idx < block->children.size() && block->children[assign_idx] != this)
3575 assign_idx++;
3576 log_assert(assign_idx < block->children.size());
3577
3578 AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
3579 assign_addr->children[0]->str = id_addr;
3580 assign_addr->children[0]->was_checked = true;
3581 block->children.insert(block->children.begin()+assign_idx+1, assign_addr);
3582
3583 AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER));
3584 case_node->children[0]->str = id_addr;
3585 for (int i = 0; i < mem_size; i++) {
3586 if (children[0]->children[0]->children[0]->type == AST_CONSTANT && int(children[0]->children[0]->children[0]->integer) != i)
3587 continue;
3588 AstNode *cond_node = new AstNode(AST_COND, AstNode::mkconst_int(i, false, addr_bits), new AstNode(AST_BLOCK));
3589 AstNode *assign_reg = new AstNode(type, new AstNode(AST_IDENTIFIER), new AstNode(AST_IDENTIFIER));
3590 if (children[0]->children.size() == 2)
3591 assign_reg->children[0]->children.push_back(children[0]->children[1]->clone());
3592 assign_reg->children[0]->str = stringf("%s[%d]", children[0]->str.c_str(), i);
3593 assign_reg->children[1]->str = id_data;
3594 cond_node->children[1]->children.push_back(assign_reg);
3595 case_node->children.push_back(cond_node);
3596 }
3597 block->children.insert(block->children.begin()+assign_idx+2, case_node);
3598
3599 children[0]->delete_children();
3600 children[0]->range_valid = false;
3601 children[0]->id2ast = NULL;
3602 children[0]->str = id_data;
3603 type = AST_ASSIGN_EQ;
3604 children[0]->was_checked = true;
3605
3606 did_something = true;
3607 }
3608
3609 if (mem2reg_check(mem2reg_set))
3610 {
3611 AstNode *bit_part_sel = NULL;
3612 if (children.size() == 2)
3613 bit_part_sel = children[1]->clone();
3614
3615 if (children[0]->children[0]->type == AST_CONSTANT)
3616 {
3617 int id = children[0]->children[0]->integer;
3618 str = stringf("%s[%d]", str.c_str(), id);
3619
3620 delete_children();
3621 range_valid = false;
3622 id2ast = NULL;
3623 }
3624 else
3625 {
3626 std::stringstream sstr;
3627 sstr << "$mem2reg_rd$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
3628 std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
3629
3630 int mem_width, mem_size, addr_bits;
3631 bool mem_signed = id2ast->is_signed;
3632 id2ast->meminfo(mem_width, mem_size, addr_bits);
3633
3634 AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
3635 wire_addr->str = id_addr;
3636 wire_addr->is_reg = true;
3637 wire_addr->was_checked = true;
3638 if (block)
3639 wire_addr->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
3640 mod->children.push_back(wire_addr);
3641 while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
3642
3643 AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
3644 wire_data->str = id_data;
3645 wire_data->is_reg = true;
3646 wire_data->was_checked = true;
3647 wire_data->is_signed = mem_signed;
3648 if (block)
3649 wire_data->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
3650 mod->children.push_back(wire_data);
3651 while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
3652
3653 AstNode *assign_addr = new AstNode(block ? AST_ASSIGN_EQ : AST_ASSIGN, new AstNode(AST_IDENTIFIER), children[0]->children[0]->clone());
3654 assign_addr->children[0]->str = id_addr;
3655 assign_addr->children[0]->was_checked = true;
3656
3657 AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER));
3658 case_node->children[0]->str = id_addr;
3659
3660 for (int i = 0; i < mem_size; i++) {
3661 if (children[0]->children[0]->type == AST_CONSTANT && int(children[0]->children[0]->integer) != i)
3662 continue;
3663 AstNode *cond_node = new AstNode(AST_COND, AstNode::mkconst_int(i, false, addr_bits), new AstNode(AST_BLOCK));
3664 AstNode *assign_reg = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), new AstNode(AST_IDENTIFIER));
3665 assign_reg->children[0]->str = id_data;
3666 assign_reg->children[0]->was_checked = true;
3667 assign_reg->children[1]->str = stringf("%s[%d]", str.c_str(), i);
3668 cond_node->children[1]->children.push_back(assign_reg);
3669 case_node->children.push_back(cond_node);
3670 }
3671
3672 std::vector<RTLIL::State> x_bits;
3673 for (int i = 0; i < mem_width; i++)
3674 x_bits.push_back(RTLIL::State::Sx);
3675
3676 AstNode *cond_node = new AstNode(AST_COND, new AstNode(AST_DEFAULT), new AstNode(AST_BLOCK));
3677 AstNode *assign_reg = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), AstNode::mkconst_bits(x_bits, false));
3678 assign_reg->children[0]->str = id_data;
3679 assign_reg->children[0]->was_checked = true;
3680 cond_node->children[1]->children.push_back(assign_reg);
3681 case_node->children.push_back(cond_node);
3682
3683 if (block)
3684 {
3685 size_t assign_idx = 0;
3686 while (assign_idx < block->children.size() && !block->children[assign_idx]->contains(this))
3687 assign_idx++;
3688 log_assert(assign_idx < block->children.size());
3689 block->children.insert(block->children.begin()+assign_idx, case_node);
3690 block->children.insert(block->children.begin()+assign_idx, assign_addr);
3691 }
3692 else
3693 {
3694 AstNode *proc = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK));
3695 proc->children[0]->children.push_back(case_node);
3696 mod->children.push_back(proc);
3697 mod->children.push_back(assign_addr);
3698 }
3699
3700 delete_children();
3701 range_valid = false;
3702 id2ast = NULL;
3703 str = id_data;
3704 }
3705
3706 if (bit_part_sel)
3707 children.push_back(bit_part_sel);
3708
3709 did_something = true;
3710 }
3711
3712 log_assert(id2ast == NULL || mem2reg_set.count(id2ast) == 0);
3713
3714 auto children_list = children;
3715 for (size_t i = 0; i < children_list.size(); i++)
3716 if (children_list[i]->mem2reg_as_needed_pass2(mem2reg_set, mod, block, async_block))
3717 did_something = true;
3718
3719 return did_something;
3720 }
3721
3722 // calculate memory dimensions
3723 void AstNode::meminfo(int &mem_width, int &mem_size, int &addr_bits)
3724 {
3725 log_assert(type == AST_MEMORY);
3726
3727 mem_width = children[0]->range_left - children[0]->range_right + 1;
3728 mem_size = children[1]->range_left - children[1]->range_right;
3729
3730 if (mem_size < 0)
3731 mem_size *= -1;
3732 mem_size += min(children[1]->range_left, children[1]->range_right) + 1;
3733
3734 addr_bits = 1;
3735 while ((1 << addr_bits) < mem_size)
3736 addr_bits++;
3737 }
3738
3739 bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
3740 {
3741 if (type == AST_FOR)
3742 recommend_const_eval = true;
3743 if (type == AST_WHILE || type == AST_REPEAT)
3744 return true;
3745 if (type == AST_FCALL && current_scope.count(str))
3746 if (current_scope[str]->has_const_only_constructs(recommend_const_eval))
3747 return true;
3748 for (auto child : children)
3749 if (child->AstNode::has_const_only_constructs(recommend_const_eval))
3750 return true;
3751 return false;
3752 }
3753
3754 bool AstNode::is_simple_const_expr()
3755 {
3756 if (type == AST_IDENTIFIER)
3757 return false;
3758 for (auto child : children)
3759 if (!child->is_simple_const_expr())
3760 return false;
3761 return true;
3762 }
3763
3764 // helper function for AstNode::eval_const_function()
3765 void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall)
3766 {
3767 if (type == AST_IDENTIFIER && variables.count(str)) {
3768 int offset = variables.at(str).offset, width = variables.at(str).val.bits.size();
3769 if (!children.empty()) {
3770 if (children.size() != 1 || children.at(0)->type != AST_RANGE)
3771 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",
3772 fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
3773 children.at(0)->replace_variables(variables, fcall);
3774 while (simplify(true, false, false, 1, -1, false, true)) { }
3775 if (!children.at(0)->range_valid)
3776 log_file_error(filename, location.first_line, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
3777 fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
3778 offset = min(children.at(0)->range_left, children.at(0)->range_right);
3779 width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);
3780 }
3781 offset -= variables.at(str).offset;
3782 std::vector<RTLIL::State> &var_bits = variables.at(str).val.bits;
3783 std::vector<RTLIL::State> new_bits(var_bits.begin() + offset, var_bits.begin() + offset + width);
3784 AstNode *newNode = mkconst_bits(new_bits, variables.at(str).is_signed);
3785 newNode->cloneInto(this);
3786 delete newNode;
3787 return;
3788 }
3789
3790 for (auto &child : children)
3791 child->replace_variables(variables, fcall);
3792 }
3793
3794 // evaluate functions with all-const arguments
3795 AstNode *AstNode::eval_const_function(AstNode *fcall)
3796 {
3797 std::map<std::string, AstNode*> backup_scope;
3798 std::map<std::string, AstNode::varinfo_t> variables;
3799 AstNode *block = new AstNode(AST_BLOCK);
3800
3801 size_t argidx = 0;
3802 for (auto child : children)
3803 {
3804 if (child->type == AST_WIRE)
3805 {
3806 while (child->simplify(true, false, false, 1, -1, false, true)) { }
3807 if (!child->range_valid)
3808 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",
3809 child->str.c_str(), fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
3810 variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1);
3811 variables[child->str].offset = min(child->range_left, child->range_right);
3812 variables[child->str].is_signed = child->is_signed;
3813 if (child->is_input && argidx < fcall->children.size())
3814 variables[child->str].val = fcall->children.at(argidx++)->bitsAsConst(variables[child->str].val.bits.size());
3815 backup_scope[child->str] = current_scope[child->str];
3816 current_scope[child->str] = child;
3817 continue;
3818 }
3819
3820 block->children.push_back(child->clone());
3821 }
3822
3823 log_assert(variables.count(str) != 0);
3824
3825 while (!block->children.empty())
3826 {
3827 AstNode *stmt = block->children.front();
3828
3829 #if 0
3830 log("-----------------------------------\n");
3831 for (auto &it : variables)
3832 log("%20s %40s\n", it.first.c_str(), log_signal(it.second.val));
3833 stmt->dumpAst(NULL, "stmt> ");
3834 #endif
3835
3836 if (stmt->type == AST_ASSIGN_EQ)
3837 {
3838 if (stmt->children.at(0)->type == AST_IDENTIFIER && stmt->children.at(0)->children.size() != 0 &&
3839 stmt->children.at(0)->children.at(0)->type == AST_RANGE)
3840 stmt->children.at(0)->children.at(0)->replace_variables(variables, fcall);
3841 stmt->children.at(1)->replace_variables(variables, fcall);
3842 while (stmt->simplify(true, false, false, 1, -1, false, true)) { }
3843
3844 if (stmt->type != AST_ASSIGN_EQ)
3845 continue;
3846
3847 if (stmt->children.at(1)->type != AST_CONSTANT)
3848 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",
3849 fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
3850
3851 if (stmt->children.at(0)->type != AST_IDENTIFIER)
3852 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",
3853 fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
3854
3855 if (!variables.count(stmt->children.at(0)->str))
3856 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",
3857 fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
3858
3859 if (stmt->children.at(0)->children.empty()) {
3860 variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size());
3861 } else {
3862 AstNode *range = stmt->children.at(0)->children.at(0);
3863 if (!range->range_valid)
3864 log_file_error(range->filename, range->location.first_line, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
3865 fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
3866 int offset = min(range->range_left, range->range_right);
3867 int width = std::abs(range->range_left - range->range_right) + 1;
3868 varinfo_t &v = variables[stmt->children.at(0)->str];
3869 RTLIL::Const r = stmt->children.at(1)->bitsAsConst(v.val.bits.size());
3870 for (int i = 0; i < width; i++)
3871 v.val.bits.at(i+offset-v.offset) = r.bits.at(i);
3872 }
3873
3874 delete block->children.front();
3875 block->children.erase(block->children.begin());
3876 continue;
3877 }
3878
3879 if (stmt->type == AST_FOR)
3880 {
3881 block->children.insert(block->children.begin(), stmt->children.at(0));
3882 stmt->children.at(3)->children.push_back(stmt->children.at(2));
3883 stmt->children.erase(stmt->children.begin() + 2);
3884 stmt->children.erase(stmt->children.begin());
3885 stmt->type = AST_WHILE;
3886 continue;
3887 }
3888
3889 if (stmt->type == AST_WHILE)
3890 {
3891 AstNode *cond = stmt->children.at(0)->clone();
3892 cond->replace_variables(variables, fcall);
3893 while (cond->simplify(true, false, false, 1, -1, false, true)) { }
3894
3895 if (cond->type != AST_CONSTANT)
3896 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",
3897 fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
3898
3899 if (cond->asBool()) {
3900 block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
3901 } else {
3902 delete block->children.front();
3903 block->children.erase(block->children.begin());
3904 }
3905
3906 delete cond;
3907 continue;
3908 }
3909
3910 if (stmt->type == AST_REPEAT)
3911 {
3912 AstNode *num = stmt->children.at(0)->clone();
3913 num->replace_variables(variables, fcall);
3914 while (num->simplify(true, false, false, 1, -1, false, true)) { }
3915
3916 if (num->type != AST_CONSTANT)
3917 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",
3918 fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
3919
3920 block->children.erase(block->children.begin());
3921 for (int i = 0; i < num->bitsAsConst().as_int(); i++)
3922 block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
3923
3924 delete stmt;
3925 delete num;
3926 continue;
3927 }
3928
3929 if (stmt->type == AST_CASE)
3930 {
3931 AstNode *expr = stmt->children.at(0)->clone();
3932 expr->replace_variables(variables, fcall);
3933 while (expr->simplify(true, false, false, 1, -1, false, true)) { }
3934
3935 AstNode *sel_case = NULL;
3936 for (size_t i = 1; i < stmt->children.size(); i++)
3937 {
3938 bool found_match = false;
3939 log_assert(stmt->children.at(i)->type == AST_COND || stmt->children.at(i)->type == AST_CONDX || stmt->children.at(i)->type == AST_CONDZ);
3940
3941 if (stmt->children.at(i)->children.front()->type == AST_DEFAULT) {
3942 sel_case = stmt->children.at(i)->children.back();
3943 continue;
3944 }
3945
3946 for (size_t j = 0; j+1 < stmt->children.at(i)->children.size() && !found_match; j++)
3947 {
3948 AstNode *cond = stmt->children.at(i)->children.at(j)->clone();
3949 cond->replace_variables(variables, fcall);
3950
3951 cond = new AstNode(AST_EQ, expr->clone(), cond);
3952 while (cond->simplify(true, false, false, 1, -1, false, true)) { }
3953
3954 if (cond->type != AST_CONSTANT)
3955 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",
3956 fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
3957
3958 found_match = cond->asBool();
3959 delete cond;
3960 }
3961
3962 if (found_match) {
3963 sel_case = stmt->children.at(i)->children.back();
3964 break;
3965 }
3966 }
3967
3968 block->children.erase(block->children.begin());
3969 if (sel_case)
3970 block->children.insert(block->children.begin(), sel_case->clone());
3971 delete stmt;
3972 delete expr;
3973 continue;
3974 }
3975
3976 if (stmt->type == AST_BLOCK)
3977 {
3978 block->children.erase(block->children.begin());
3979 block->children.insert(block->children.begin(), stmt->children.begin(), stmt->children.end());
3980 stmt->children.clear();
3981 delete stmt;
3982 continue;
3983 }
3984
3985 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",
3986 fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
3987 log_abort();
3988 }
3989
3990 delete block;
3991
3992 for (auto &it : backup_scope)
3993 if (it.second == NULL)
3994 current_scope.erase(it.first);
3995 else
3996 current_scope[it.first] = it.second;
3997
3998 return AstNode::mkconst_bits(variables.at(str).val.bits, variables.at(str).is_signed);
3999 }
4000
4001 void AstNode::allocateDefaultEnumValues()
4002 {
4003 log_assert(type==AST_ENUM);
4004 int last_enum_int = -1;
4005 for (auto node : children) {
4006 log_assert(node->type==AST_ENUM_ITEM);
4007 node->attributes["\\enum_base_type"] = mkconst_str(str);
4008 for (size_t i = 0; i < node->children.size(); i++) {
4009 switch (node->children[i]->type) {
4010 case AST_NONE:
4011 // replace with auto-incremented constant
4012 delete node->children[i];
4013 node->children[i] = AstNode::mkconst_int(++last_enum_int, true);
4014 break;
4015 case AST_CONSTANT:
4016 // explicit constant (or folded expression)
4017 // TODO: can't extend 'x or 'z item
4018 last_enum_int = node->children[i]->integer;
4019 break;
4020 default:
4021 // ignore ranges
4022 break;
4023 }
4024 // TODO: range check
4025 }
4026 }
4027 }
4028
4029 YOSYS_NAMESPACE_END