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