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