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