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