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