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