yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
simplify.cc
Go to the documentation of this file.
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"
32 #include "ast.h"
33 
34 #include <sstream>
35 #include <stdarg.h>
36 #include <stdlib.h>
37 #include <math.h>
38 
40 
41 using namespace AST;
42 using namespace AST_INTERNAL;
43 
44 // convert the AST into a simpler AST that has all parameters subsitited by their
45 // values, unrolled for-loops, expanded generate blocks, etc. when this function
46 // is done with an AST it can be converted into RTLIL using genRTLIL().
47 //
48 // this function also does all name resolving and sets the id2ast member of all
49 // nodes that link to a different node using names and lexical scoping.
50 bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
51 {
52  AstNode *newNode = NULL;
53  bool did_something = false;
54 
55 #if 0
56  log("-------------\n");
57  log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
58  int(const_fold), int(at_zero), int(in_lvalue), int(stage), int(width_hint), int(sign_hint), int(in_param));
59  dumpAst(NULL, "> ");
60 #endif
61 
62  if (stage == 0)
63  {
64  log_assert(type == AST_MODULE);
65 
66  while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { }
67 
68  if (!flag_nomem2reg && !get_bool_attribute("\\nomem2reg"))
69  {
70  std::map<AstNode*, std::set<std::string>> mem2reg_places;
71  std::map<AstNode*, uint32_t> mem2reg_candidates, dummy_proc_flags;
72  uint32_t flags = flag_mem2reg ? AstNode::MEM2REG_FL_ALL : 0;
73  mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, dummy_proc_flags, flags);
74 
75  std::set<AstNode*> mem2reg_set;
76  for (auto &it : mem2reg_candidates)
77  {
78  AstNode *mem = it.first;
79  uint32_t memflags = it.second;
80  log_assert((memflags & ~0x00ffff00) == 0);
81 
82  if (mem->get_bool_attribute("\\nomem2reg"))
83  continue;
84 
85  if (memflags & AstNode::MEM2REG_FL_FORCED)
86  goto silent_activate;
87 
88  if (memflags & AstNode::MEM2REG_FL_EQ2)
89  goto verbose_activate;
90 
91  if (memflags & AstNode::MEM2REG_FL_SET_ASYNC)
92  goto verbose_activate;
93 
94  if ((memflags & AstNode::MEM2REG_FL_SET_INIT) && (memflags & AstNode::MEM2REG_FL_SET_ELSE))
95  goto verbose_activate;
96 
97  if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS)
98  goto verbose_activate;
99 
100  // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
101  continue;
102 
103  verbose_activate:
104  if (mem2reg_set.count(mem) == 0) {
105  log_warning("Replacing memory %s with list of registers.", mem->str.c_str());
106  bool first_element = true;
107  for (auto &place : mem2reg_places[it.first]) {
108  log("%s%s", first_element ? " See " : ", ", place.c_str());
109  first_element = false;
110  }
111  log("\n");
112  }
113 
114  silent_activate:
115  // log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
116  mem2reg_set.insert(mem);
117  }
118 
119  for (auto node : mem2reg_set)
120  {
121  int mem_width, mem_size, addr_bits;
122  node->meminfo(mem_width, mem_size, addr_bits);
123 
124  for (int i = 0; i < mem_size; i++) {
125  AstNode *reg = new AstNode(AST_WIRE, new AstNode(AST_RANGE,
126  mkconst_int(mem_width-1, true), mkconst_int(0, true)));
127  reg->str = stringf("%s[%d]", node->str.c_str(), i);
128  reg->is_reg = true;
129  reg->is_signed = node->is_signed;
130  children.push_back(reg);
131  while (reg->simplify(true, false, false, 1, -1, false, false)) { }
132  }
133  }
134 
135  mem2reg_as_needed_pass2(mem2reg_set, this, NULL);
136 
137  for (size_t i = 0; i < children.size(); i++) {
138  if (mem2reg_set.count(children[i]) > 0) {
139  delete children[i];
140  children.erase(children.begin() + (i--));
141  }
142  }
143  }
144 
145  while (simplify(const_fold, at_zero, in_lvalue, 2, width_hint, sign_hint, in_param)) { }
146  return false;
147  }
148 
149  current_filename = filename;
150  set_line_num(linenum);
151 
152  // we do not look inside a task or function
153  // (but as soon as a task of function is instanciated we process the generated AST as usual)
154  if (type == AST_FUNCTION || type == AST_TASK)
155  return false;
156 
157  // deactivate all calls to non-synthesis system taks
158  if ((type == AST_FCALL || type == AST_TCALL) && (str == "$display" || str == "$stop" || str == "$finish")) {
159  delete_children();
160  str = std::string();
161  }
162 
163  // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
164  if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX)
165  const_fold = true;
166  if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM))
167  const_fold = true;
168 
169  // in certain cases a function must be evaluated constant. this is what in_param controls.
170  if (type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_PREFIX)
171  in_param = true;
172 
173  std::map<std::string, AstNode*> backup_scope;
174 
175  // create name resolution entries for all objects with names
176  // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
177  if (type == AST_MODULE) {
178  current_scope.clear();
179  std::map<std::string, AstNode*> this_wire_scope;
180  for (size_t i = 0; i < children.size(); i++) {
181  AstNode *node = children[i];
182  if (node->type == AST_WIRE) {
183  if (this_wire_scope.count(node->str) > 0) {
184  AstNode *first_node = this_wire_scope[node->str];
185  if (!node->is_input && !node->is_output && node->is_reg && node->children.size() == 0)
186  goto wires_are_compatible;
187  if (first_node->children.size() != node->children.size())
188  goto wires_are_incompatible;
189  for (size_t j = 0; j < node->children.size(); j++) {
190  AstNode *n1 = first_node->children[j], *n2 = node->children[j];
191  if (n1->type == AST_RANGE && n2->type == AST_RANGE && n1->range_valid && n2->range_valid) {
192  if (n1->range_left != n2->range_left)
193  goto wires_are_incompatible;
194  if (n1->range_right != n2->range_right)
195  goto wires_are_incompatible;
196  } else if (*n1 != *n2)
197  goto wires_are_incompatible;
198  }
199  if (first_node->range_left != node->range_left)
200  goto wires_are_incompatible;
201  if (first_node->range_right != node->range_right)
202  goto wires_are_incompatible;
203  if (first_node->port_id == 0 && (node->is_input || node->is_output))
204  goto wires_are_incompatible;
205  wires_are_compatible:
206  if (node->is_input)
207  first_node->is_input = true;
208  if (node->is_output)
209  first_node->is_output = true;
210  if (node->is_reg)
211  first_node->is_reg = true;
212  if (node->is_signed)
213  first_node->is_signed = true;
214  for (auto &it : node->attributes) {
215  if (first_node->attributes.count(it.first) > 0)
216  delete first_node->attributes[it.first];
217  first_node->attributes[it.first] = it.second->clone();
218  }
219  children.erase(children.begin()+(i--));
220  did_something = true;
221  delete node;
222  continue;
223  wires_are_incompatible:
224  if (stage > 1)
225  log_error("Incompatible re-declaration of wire %s at %s:%d.\n", node->str.c_str(), filename.c_str(), linenum);
226  continue;
227  }
228  this_wire_scope[node->str] = node;
229  }
230  if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
231  node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL) {
232  backup_scope[node->str] = current_scope[node->str];
233  current_scope[node->str] = node;
234  }
235  }
236  for (size_t i = 0; i < children.size(); i++) {
237  AstNode *node = children[i];
238  if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE)
239  while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM))
240  did_something = true;
241  }
242  }
243 
244  auto backup_current_block = current_block;
245  auto backup_current_block_child = current_block_child;
246  auto backup_current_top_block = current_top_block;
247 
248  int backup_width_hint = width_hint;
249  bool backup_sign_hint = sign_hint;
250 
251  bool detect_width_simple = false;
252  bool child_0_is_self_determined = false;
253  bool child_1_is_self_determined = false;
254  bool child_2_is_self_determined = false;
255  bool children_are_self_determined = false;
256  bool reset_width_after_children = false;
257 
258  switch (type)
259  {
260  case AST_ASSIGN_EQ:
261  case AST_ASSIGN_LE:
262  case AST_ASSIGN:
263  while (!children[0]->basic_prep && children[0]->simplify(false, false, true, stage, -1, false, in_param) == true)
264  did_something = true;
265  while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, in_param) == true)
266  did_something = true;
267  children[0]->detectSignWidth(backup_width_hint, backup_sign_hint);
268  children[1]->detectSignWidth(width_hint, sign_hint);
269  width_hint = std::max(width_hint, backup_width_hint);
270  child_0_is_self_determined = true;
271  break;
272 
273  case AST_PARAMETER:
274  case AST_LOCALPARAM:
275  while (!children[0]->basic_prep && children[0]->simplify(false, false, false, stage, -1, false, true) == true)
276  did_something = true;
277  children[0]->detectSignWidth(width_hint, sign_hint);
278  if (children.size() > 1 && children[1]->type == AST_RANGE) {
279  while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, true) == true)
280  did_something = true;
281  if (!children[1]->range_valid)
282  log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
283  width_hint = std::max(width_hint, children[1]->range_left - children[1]->range_right + 1);
284  }
285  break;
286 
287  case AST_TO_BITS:
288  case AST_TO_SIGNED:
289  case AST_TO_UNSIGNED:
290  case AST_CONCAT:
291  case AST_REPLICATE:
292  case AST_REDUCE_AND:
293  case AST_REDUCE_OR:
294  case AST_REDUCE_XOR:
295  case AST_REDUCE_XNOR:
296  case AST_REDUCE_BOOL:
297  detect_width_simple = true;
298  children_are_self_determined = true;
299  break;
300 
301  case AST_NEG:
302  case AST_BIT_NOT:
303  case AST_POS:
304  case AST_BIT_AND:
305  case AST_BIT_OR:
306  case AST_BIT_XOR:
307  case AST_BIT_XNOR:
308  case AST_ADD:
309  case AST_SUB:
310  case AST_MUL:
311  case AST_DIV:
312  case AST_MOD:
313  detect_width_simple = true;
314  break;
315 
316  case AST_SHIFT_LEFT:
317  case AST_SHIFT_RIGHT:
318  case AST_SHIFT_SLEFT:
319  case AST_SHIFT_SRIGHT:
320  case AST_POW:
321  detect_width_simple = true;
322  child_1_is_self_determined = true;
323  break;
324 
325  case AST_LT:
326  case AST_LE:
327  case AST_EQ:
328  case AST_NE:
329  case AST_EQX:
330  case AST_NEX:
331  case AST_GE:
332  case AST_GT:
333  width_hint = -1;
334  sign_hint = true;
335  for (auto child : children) {
336  while (!child->basic_prep && child->simplify(false, false, in_lvalue, stage, -1, false, in_param) == true)
337  did_something = true;
338  child->detectSignWidthWorker(width_hint, sign_hint);
339  }
340  reset_width_after_children = true;
341  break;
342 
343  case AST_LOGIC_AND:
344  case AST_LOGIC_OR:
345  case AST_LOGIC_NOT:
346  detect_width_simple = true;
347  children_are_self_determined = true;
348  break;
349 
350  case AST_TERNARY:
351  detect_width_simple = true;
352  child_0_is_self_determined = true;
353  break;
354 
355  case AST_MEMRD:
356  detect_width_simple = true;
357  children_are_self_determined = true;
358  break;
359 
360  default:
361  width_hint = -1;
362  sign_hint = false;
363  }
364 
365  if (detect_width_simple && width_hint < 0) {
366  if (type == AST_REPLICATE)
367  while (children[0]->simplify(true, false, in_lvalue, stage, -1, false, true) == true)
368  did_something = true;
369  for (auto child : children)
370  while (!child->basic_prep && child->simplify(false, false, in_lvalue, stage, -1, false, in_param) == true)
371  did_something = true;
372  detectSignWidth(width_hint, sign_hint);
373  }
374 
375  if (type == AST_TERNARY) {
376  int width_hint_left, width_hint_right;
377  bool sign_hint_left, sign_hint_right;
378  bool found_real_left, found_real_right;
379  children[1]->detectSignWidth(width_hint_left, sign_hint_left, &found_real_left);
380  children[2]->detectSignWidth(width_hint_right, sign_hint_right, &found_real_right);
381  if (found_real_left || found_real_right) {
382  child_1_is_self_determined = true;
383  child_2_is_self_determined = true;
384  }
385  }
386 
387  if (const_fold && type == AST_CASE)
388  {
389  while (children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { }
390  if (children[0]->type == AST_CONSTANT && children[0]->bits_only_01()) {
391  std::vector<AstNode*> new_children;
392  new_children.push_back(children[0]);
393  for (int i = 1; i < GetSize(children); i++) {
394  AstNode *child = children[i];
395  log_assert(child->type == AST_COND);
396  for (auto v : child->children) {
397  if (v->type == AST_DEFAULT)
398  goto keep_const_cond;
399  if (v->type == AST_BLOCK)
400  continue;
401  while (v->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { }
402  if (v->type == AST_CONSTANT && v->bits_only_01()) {
403  if (v->bits == children[0]->bits) {
404  while (i+1 < GetSize(children))
405  delete children[++i];
406  goto keep_const_cond;
407  }
408  continue;
409  }
410  goto keep_const_cond;
411  }
412  if (0)
413  keep_const_cond:
414  new_children.push_back(child);
415  else
416  delete child;
417  }
418  new_children.swap(children);
419  }
420  }
421 
422  // simplify all children first
423  // (iterate by index as e.g. auto wires can add new children in the process)
424  for (size_t i = 0; i < children.size(); i++) {
425  bool did_something_here = true;
426  if ((type == AST_GENFOR || type == AST_FOR) && i >= 3)
427  break;
428  if ((type == AST_GENIF || type == AST_GENCASE) && i >= 1)
429  break;
430  if (type == AST_GENBLOCK)
431  break;
432  if (type == AST_BLOCK && !str.empty())
433  break;
434  if (type == AST_PREFIX && i >= 1)
435  break;
436  while (did_something_here && i < children.size()) {
437  bool const_fold_here = const_fold, in_lvalue_here = in_lvalue;
438  int width_hint_here = width_hint;
439  bool sign_hint_here = sign_hint;
440  bool in_param_here = in_param;
441  if (i == 0 && (type == AST_REPLICATE || type == AST_WIRE))
442  const_fold_here = true, in_param_here = true;
443  if (type == AST_PARAMETER || type == AST_LOCALPARAM)
444  const_fold_here = true;
445  if (i == 0 && (type == AST_ASSIGN || type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE))
446  in_lvalue_here = true;
447  if (type == AST_BLOCK) {
448  current_block = this;
449  current_block_child = children[i];
450  }
451  if ((type == AST_ALWAYS || type == AST_INITIAL) && children[i]->type == AST_BLOCK)
452  current_top_block = children[i];
453  if (i == 0 && child_0_is_self_determined)
454  width_hint_here = -1, sign_hint_here = false;
455  if (i == 1 && child_1_is_self_determined)
456  width_hint_here = -1, sign_hint_here = false;
457  if (i == 2 && child_2_is_self_determined)
458  width_hint_here = -1, sign_hint_here = false;
459  if (children_are_self_determined)
460  width_hint_here = -1, sign_hint_here = false;
461  did_something_here = children[i]->simplify(const_fold_here, at_zero, in_lvalue_here, stage, width_hint_here, sign_hint_here, in_param_here);
462  if (did_something_here)
463  did_something = true;
464  }
465  if (stage == 2 && children[i]->type == AST_INITIAL && current_ast_mod != this) {
466  current_ast_mod->children.push_back(children[i]);
467  children.erase(children.begin() + (i--));
468  did_something = true;
469  }
470  }
471  for (auto &attr : attributes) {
472  while (attr.second->simplify(true, false, false, stage, -1, false, true))
473  did_something = true;
474  }
475 
476  if (reset_width_after_children) {
477  width_hint = backup_width_hint;
478  sign_hint = backup_sign_hint;
479  if (width_hint < 0)
480  detectSignWidth(width_hint, sign_hint);
481  }
482 
483  current_block = backup_current_block;
484  current_block_child = backup_current_block_child;
485  current_top_block = backup_current_top_block;
486 
487  for (auto it = backup_scope.begin(); it != backup_scope.end(); it++) {
488  if (it->second == NULL)
489  current_scope.erase(it->first);
490  else
491  current_scope[it->first] = it->second;
492  }
493 
494  current_filename = filename;
495  set_line_num(linenum);
496 
497  if (type == AST_MODULE)
498  current_scope.clear();
499 
500  // convert defparam nodes to cell parameters
501  if (type == AST_DEFPARAM && !str.empty()) {
502  size_t pos = str.rfind('.');
503  if (pos == std::string::npos)
504  log_error("Defparam `%s' does not contain a dot (module/parameter separator) at %s:%d!\n",
505  RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
506  std::string modname = str.substr(0, pos), paraname = "\\" + str.substr(pos+1);
507  if (current_scope.count(modname) == 0 || current_scope.at(modname)->type != AST_CELL)
508  log_error("Can't find cell for defparam `%s . %s` at %s:%d!\n", RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paraname).c_str(), filename.c_str(), linenum);
509  AstNode *cell = current_scope.at(modname), *paraset = clone();
510  cell->children.insert(cell->children.begin() + 1, paraset);
511  paraset->type = AST_PARASET;
512  paraset->str = paraname;
513  str.clear();
514  }
515 
516  // resolve constant prefixes
517  if (type == AST_PREFIX) {
518  if (children[0]->type != AST_CONSTANT) {
519  // dumpAst(NULL, "> ");
520  log_error("Index in generate block prefix syntax at %s:%d is not constant!\n", filename.c_str(), linenum);
521  }
522  log_assert(children[1]->type == AST_IDENTIFIER);
523  newNode = children[1]->clone();
524  const char *second_part = children[1]->str.c_str();
525  if (second_part[0] == '\\')
526  second_part++;
527  newNode->str = stringf("%s[%d].%s", str.c_str(), children[0]->integer, second_part);
528  goto apply_newNode;
529  }
530 
531  // evaluate TO_BITS nodes
532  if (type == AST_TO_BITS) {
533  if (children[0]->type != AST_CONSTANT)
534  log_error("Left operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
535  if (children[1]->type != AST_CONSTANT)
536  log_error("Right operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
537  RTLIL::Const new_value = children[1]->bitsAsConst(children[0]->bitsAsConst().as_int(), children[1]->is_signed);
538  newNode = mkconst_bits(new_value.bits, children[1]->is_signed);
539  goto apply_newNode;
540  }
541 
542  // annotate constant ranges
543  if (type == AST_RANGE) {
544  bool old_range_valid = range_valid;
545  range_valid = false;
546  range_swapped = false;
547  range_left = -1;
548  range_right = 0;
549  log_assert(children.size() >= 1);
550  if (children[0]->type == AST_CONSTANT) {
551  range_valid = true;
552  range_left = children[0]->integer;
553  if (children.size() == 1)
554  range_right = range_left;
555  }
556  if (children.size() >= 2) {
557  if (children[1]->type == AST_CONSTANT)
558  range_right = children[1]->integer;
559  else
560  range_valid = false;
561  }
562  if (old_range_valid != range_valid)
563  did_something = true;
564  if (range_valid && range_left >= 0 && range_right > range_left) {
565  int tmp = range_right;
566  range_right = range_left;
567  range_left = tmp;
568  range_swapped = true;
569  }
570  }
571 
572  // annotate wires with their ranges
573  if (type == AST_WIRE) {
574  if (children.size() > 0) {
575  if (children[0]->range_valid) {
576  if (!range_valid)
577  did_something = true;
578  range_valid = true;
579  range_swapped = children[0]->range_swapped;
580  range_left = children[0]->range_left;
581  range_right = children[0]->range_right;
582  }
583  } else {
584  if (!range_valid)
585  did_something = true;
586  range_valid = true;
587  range_swapped = false;
588  range_left = 0;
589  range_right = 0;
590  }
591  }
592 
593  // resolve multiranges on memory decl
594  if (type == AST_MEMORY && children.size() > 1 && children[1]->type == AST_MULTIRANGE)
595  {
596  int total_size = 1;
597  multirange_dimensions.clear();
598  for (auto range : children[1]->children) {
599  if (!range->range_valid)
600  log_error("Non-constant range on memory decl at %s:%d.\n", filename.c_str(), linenum);
601  multirange_dimensions.push_back(std::min(range->range_left, range->range_right));
602  multirange_dimensions.push_back(std::max(range->range_left, range->range_right) - std::min(range->range_left, range->range_right) + 1);
603  total_size *= multirange_dimensions.back();
604  }
605  delete children[1];
606  children[1] = new AstNode(AST_RANGE, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size-1, true));
607  did_something = true;
608  }
609 
610  // resolve multiranges on memory access
611  if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY && children.size() > 0 && children[0]->type == AST_MULTIRANGE)
612  {
613  AstNode *index_expr = nullptr;
614 
615  for (int i = 0; 2*i < GetSize(id2ast->multirange_dimensions); i++)
616  {
617  if (GetSize(children[0]->children) < i)
618  log_error("Insufficient number of array indices for %s at %s:%d.\n", log_id(str), filename.c_str(), linenum);
619 
620  AstNode *new_index_expr = children[0]->children[i]->children.at(0)->clone();
621 
622  if (id2ast->multirange_dimensions[2*i])
623  new_index_expr = new AstNode(AST_SUB, new_index_expr, AstNode::mkconst_int(id2ast->multirange_dimensions[2*i], true));
624 
625  if (i == 0)
626  index_expr = new_index_expr;
627  else
628  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);
629  }
630 
631  for (int i = GetSize(id2ast->multirange_dimensions)/1; i < GetSize(children[0]->children); i++)
632  children.push_back(children[0]->children[i]->clone());
633 
634  delete children[0];
635  if (index_expr == nullptr)
636  children.erase(children.begin());
637  else
638  children[0] = new AstNode(AST_RANGE, index_expr);
639 
640  did_something = true;
641  }
642 
643  // trim/extend parameters
644  if (type == AST_PARAMETER || type == AST_LOCALPARAM) {
645  if (children.size() > 1 && children[1]->type == AST_RANGE) {
646  if (!children[1]->range_valid)
647  log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
648  int width = children[1]->range_left - children[1]->range_right + 1;
649  if (children[0]->type == AST_REALVALUE) {
650  RTLIL::Const constvalue = children[0]->realAsConst(width);
651  log_warning("converting real value %e to binary %s at %s:%d.\n",
652  children[0]->realvalue, log_signal(constvalue), filename.c_str(), linenum);
653  delete children[0];
654  children[0] = mkconst_bits(constvalue.bits, sign_hint);
655  did_something = true;
656  }
657  if (children[0]->type == AST_CONSTANT) {
658  if (width != int(children[0]->bits.size())) {
659  RTLIL::SigSpec sig(children[0]->bits);
660  sig.extend_u0(width, children[0]->is_signed);
661  AstNode *old_child_0 = children[0];
662  children[0] = mkconst_bits(sig.as_const().bits, children[0]->is_signed);
663  delete old_child_0;
664  }
665  children[0]->is_signed = is_signed;
666  }
667  range_valid = true;
668  range_swapped = children[1]->range_swapped;
669  range_left = children[1]->range_left;
670  range_right = children[1]->range_right;
671  } else
672  if (children.size() > 1 && children[1]->type == AST_REALVALUE && children[0]->type == AST_CONSTANT) {
673  double as_realvalue = children[0]->asReal(sign_hint);
674  delete children[0];
675  children[0] = new AstNode(AST_REALVALUE);
676  children[0]->realvalue = as_realvalue;
677  did_something = true;
678  }
679  }
680 
681  // annotate identifiers using scope resolution and create auto-wires as needed
682  if (type == AST_IDENTIFIER) {
683  if (current_scope.count(str) == 0) {
684  for (auto node : current_ast_mod->children) {
685  if ((node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
686  node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION) && str == node->str) {
687  current_scope[node->str] = node;
688  break;
689  }
690  }
691  }
692  if (current_scope.count(str) == 0) {
693  // log_warning("Creating auto-wire `%s' in module `%s'.\n", str.c_str(), current_ast_mod->str.c_str());
694  AstNode *auto_wire = new AstNode(AST_AUTOWIRE);
695  auto_wire->str = str;
696  current_ast_mod->children.push_back(auto_wire);
697  current_scope[str] = auto_wire;
698  did_something = true;
699  }
700  if (id2ast != current_scope[str]) {
701  id2ast = current_scope[str];
702  did_something = true;
703  }
704  }
705 
706  // split memory access with bit select to individual statements
707  if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue)
708  {
709  if (id2ast == NULL || id2ast->type != AST_MEMORY || children[0]->children.size() != 1)
710  log_error("Invalid bit-select on memory access at %s:%d!\n", filename.c_str(), linenum);
711 
712  int mem_width, mem_size, addr_bits;
713  id2ast->meminfo(mem_width, mem_size, addr_bits);
714 
715  std::stringstream sstr;
716  sstr << "$mem2bits$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
717  std::string wire_id = sstr.str();
718 
719  AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
720  wire->str = wire_id;
721  if (current_block)
722  wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
723  current_ast_mod->children.push_back(wire);
724  while (wire->simplify(true, false, false, 1, -1, false, false)) { }
725 
726  AstNode *data = clone();
727  delete data->children[1];
728  data->children.pop_back();
729 
730  AstNode *assign = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), data);
731  assign->children[0]->str = wire_id;
732 
733  if (current_block)
734  {
735  size_t assign_idx = 0;
736  while (assign_idx < current_block->children.size() && current_block->children[assign_idx] != current_block_child)
737  assign_idx++;
738  log_assert(assign_idx < current_block->children.size());
739  current_block->children.insert(current_block->children.begin()+assign_idx, assign);
740  wire->is_reg = true;
741  }
742  else
743  {
744  AstNode *proc = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK));
745  proc->children[0]->children.push_back(assign);
746  current_ast_mod->children.push_back(proc);
747  }
748 
749  newNode = new AstNode(AST_IDENTIFIER, children[1]->clone());
750  newNode->str = wire_id;
751  newNode->id2ast = wire;
752  goto apply_newNode;
753  }
754 
755  if (type == AST_WHILE)
756  log_error("While loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum);
757 
758  if (type == AST_REPEAT)
759  log_error("Repeat loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum);
760 
761  // unroll for loops and generate-for blocks
762  if ((type == AST_GENFOR || type == AST_FOR) && children.size() != 0)
763  {
764  AstNode *init_ast = children[0];
765  AstNode *while_ast = children[1];
766  AstNode *next_ast = children[2];
767  AstNode *body_ast = children[3];
768 
769  while (body_ast->type == AST_GENBLOCK && body_ast->str.empty() &&
770  body_ast->children.size() == 1 && body_ast->children.at(0)->type == AST_GENBLOCK)
771  body_ast = body_ast->children.at(0);
772 
773  if (init_ast->type != AST_ASSIGN_EQ)
774  log_error("Unsupported 1st expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
775  if (next_ast->type != AST_ASSIGN_EQ)
776  log_error("Unsupported 3rd expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
777 
778  if (type == AST_GENFOR) {
779  if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_GENVAR)
780  log_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a gen var!\n", filename.c_str(), linenum);
781  if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_GENVAR)
782  log_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a gen var!\n", filename.c_str(), linenum);
783  } else {
784  if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_WIRE)
785  log_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a register!\n", filename.c_str(), linenum);
786  if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_WIRE)
787  log_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a register!\n", filename.c_str(), linenum);
788  }
789 
790  if (init_ast->children[0]->id2ast != next_ast->children[0]->id2ast)
791  log_error("Incompatible left-hand sides in 1st and 3rd expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
792 
793  // eval 1st expression
794  AstNode *varbuf = init_ast->children[1]->clone();
795  while (varbuf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
796 
797  if (varbuf->type != AST_CONSTANT)
798  log_error("Right hand side of 1st expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
799 
800  varbuf = new AstNode(AST_LOCALPARAM, varbuf);
801  varbuf->str = init_ast->children[0]->str;
802 
803  AstNode *backup_scope_varbuf = current_scope[varbuf->str];
804  current_scope[varbuf->str] = varbuf;
805 
806  size_t current_block_idx = 0;
807  if (type == AST_FOR) {
808  while (current_block_idx < current_block->children.size() &&
809  current_block->children[current_block_idx] != current_block_child)
810  current_block_idx++;
811  }
812 
813  while (1)
814  {
815  // eval 2nd expression
816  AstNode *buf = while_ast->clone();
817  while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
818 
819  if (buf->type != AST_CONSTANT)
820  log_error("2nd expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
821 
822  if (buf->integer == 0) {
823  delete buf;
824  break;
825  }
826  delete buf;
827 
828  // expand body
829  int index = varbuf->children[0]->integer;
830  if (body_ast->type == AST_GENBLOCK)
831  buf = body_ast->clone();
832  else
833  buf = new AstNode(AST_GENBLOCK, body_ast->clone());
834  if (buf->str.empty()) {
835  std::stringstream sstr;
836  sstr << "$genblock$" << filename << ":" << linenum << "$" << (autoidx++);
837  buf->str = sstr.str();
838  }
839  std::map<std::string, std::string> name_map;
840  std::stringstream sstr;
841  sstr << buf->str << "[" << index << "].";
842  buf->expand_genblock(varbuf->str, sstr.str(), name_map);
843 
844  if (type == AST_GENFOR) {
845  for (size_t i = 0; i < buf->children.size(); i++) {
846  buf->children[i]->simplify(false, false, false, stage, -1, false, false);
847  current_ast_mod->children.push_back(buf->children[i]);
848  }
849  } else {
850  for (size_t i = 0; i < buf->children.size(); i++)
851  current_block->children.insert(current_block->children.begin() + current_block_idx++, buf->children[i]);
852  }
853  buf->children.clear();
854  delete buf;
855 
856  // eval 3rd expression
857  buf = next_ast->children[1]->clone();
858  while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
859 
860  if (buf->type != AST_CONSTANT)
861  log_error("Right hand side of 3rd expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
862 
863  delete varbuf->children[0];
864  varbuf->children[0] = buf;
865  }
866 
867  current_scope[varbuf->str] = backup_scope_varbuf;
868  delete varbuf;
869  delete_children();
870  did_something = true;
871  }
872 
873  // transform block with name
874  if (type == AST_BLOCK && !str.empty())
875  {
876  std::map<std::string, std::string> name_map;
877  expand_genblock(std::string(), str + ".", name_map);
878 
879  std::vector<AstNode*> new_children;
880  for (size_t i = 0; i < children.size(); i++)
881  if (children[i]->type == AST_WIRE) {
882  children[i]->simplify(false, false, false, stage, -1, false, false);
883  current_ast_mod->children.push_back(children[i]);
884  current_scope[children[i]->str] = children[i];
885  } else
886  new_children.push_back(children[i]);
887 
888  children.swap(new_children);
889  did_something = true;
890  str.clear();
891  }
892 
893  // simplify unconditional generate block
894  if (type == AST_GENBLOCK && children.size() != 0)
895  {
896  if (!str.empty()) {
897  std::map<std::string, std::string> name_map;
898  expand_genblock(std::string(), str + ".", name_map);
899  }
900 
901  for (size_t i = 0; i < children.size(); i++) {
902  children[i]->simplify(false, false, false, stage, -1, false, false);
903  current_ast_mod->children.push_back(children[i]);
904  }
905 
906  children.clear();
907  did_something = true;
908  }
909 
910  // simplify generate-if blocks
911  if (type == AST_GENIF && children.size() != 0)
912  {
913  AstNode *buf = children[0]->clone();
914  while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
915  if (buf->type != AST_CONSTANT) {
916  // for (auto f : log_files)
917  // dumpAst(f, "verilog-ast> ");
918  log_error("Condition for generate if at %s:%d is not constant!\n", filename.c_str(), linenum);
919  }
920  if (buf->asBool() != 0) {
921  delete buf;
922  buf = children[1]->clone();
923  } else {
924  delete buf;
925  buf = children.size() > 2 ? children[2]->clone() : NULL;
926  }
927 
928  if (buf)
929  {
930  if (buf->type != AST_GENBLOCK)
931  buf = new AstNode(AST_GENBLOCK, buf);
932 
933  if (!buf->str.empty()) {
934  std::map<std::string, std::string> name_map;
935  buf->expand_genblock(std::string(), buf->str + ".", name_map);
936  }
937 
938  for (size_t i = 0; i < buf->children.size(); i++) {
939  buf->children[i]->simplify(false, false, false, stage, -1, false, false);
940  current_ast_mod->children.push_back(buf->children[i]);
941  }
942 
943  buf->children.clear();
944  delete buf;
945  }
946 
947  delete_children();
948  did_something = true;
949  }
950 
951  // simplify generate-case blocks
952  if (type == AST_GENCASE && children.size() != 0)
953  {
954  AstNode *buf = children[0]->clone();
955  while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
956  if (buf->type != AST_CONSTANT) {
957  // for (auto f : log_files)
958  // dumpAst(f, "verilog-ast> ");
959  log_error("Condition for generate case at %s:%d is not constant!\n", filename.c_str(), linenum);
960  }
961 
962  bool ref_signed = buf->is_signed;
963  RTLIL::Const ref_value = buf->bitsAsConst();
964  delete buf;
965 
966  AstNode *selected_case = NULL;
967  for (size_t i = 1; i < children.size(); i++)
968  {
969  log_assert(children.at(i)->type == AST_COND);
970 
971  AstNode *this_genblock = NULL;
972  for (auto child : children.at(i)->children) {
973  log_assert(this_genblock == NULL);
974  if (child->type == AST_GENBLOCK)
975  this_genblock = child;
976  }
977 
978  for (auto child : children.at(i)->children)
979  {
980  if (child->type == AST_DEFAULT) {
981  if (selected_case == NULL)
982  selected_case = this_genblock;
983  continue;
984  }
985  if (child->type == AST_GENBLOCK)
986  continue;
987 
988  buf = child->clone();
989  while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
990  if (buf->type != AST_CONSTANT) {
991  // for (auto f : log_files)
992  // dumpAst(f, "verilog-ast> ");
993  log_error("Expression in generate case at %s:%d is not constant!\n", filename.c_str(), linenum);
994  }
995 
996  bool is_selected = RTLIL::const_eq(ref_value, buf->bitsAsConst(), ref_signed && buf->is_signed, ref_signed && buf->is_signed, 1).as_bool();
997  delete buf;
998 
999  if (is_selected) {
1000  selected_case = this_genblock;
1001  i = children.size();
1002  break;
1003  }
1004  }
1005  }
1006 
1007  if (selected_case != NULL)
1008  {
1009  log_assert(selected_case->type == AST_GENBLOCK);
1010  buf = selected_case->clone();
1011 
1012  if (!buf->str.empty()) {
1013  std::map<std::string, std::string> name_map;
1014  buf->expand_genblock(std::string(), buf->str + ".", name_map);
1015  }
1016 
1017  for (size_t i = 0; i < buf->children.size(); i++) {
1018  buf->children[i]->simplify(false, false, false, stage, -1, false, false);
1019  current_ast_mod->children.push_back(buf->children[i]);
1020  }
1021 
1022  buf->children.clear();
1023  delete buf;
1024  }
1025 
1026  delete_children();
1027  did_something = true;
1028  }
1029 
1030  // unroll cell arrays
1031  if (type == AST_CELLARRAY)
1032  {
1033  if (!children.at(0)->range_valid)
1034  log_error("Non-constant array range on cell array at %s:%d.\n", filename.c_str(), linenum);
1035 
1036  newNode = new AstNode(AST_GENBLOCK);
1037  int num = std::max(children.at(0)->range_left, children.at(0)->range_right) - std::min(children.at(0)->range_left, children.at(0)->range_right) + 1;
1038 
1039  for (int i = 0; i < num; i++) {
1040  int idx = children.at(0)->range_left > children.at(0)->range_right ? children.at(0)->range_right + i : children.at(0)->range_right - i;
1041  AstNode *new_cell = children.at(1)->clone();
1042  newNode->children.push_back(new_cell);
1043  new_cell->str += stringf("[%d]", idx);
1044  if (new_cell->type == AST_PRIMITIVE) {
1045  log_error("Cell arrays of primitives are currently not supported at %s:%d.\n", filename.c_str(), linenum);
1046  } else {
1047  log_assert(new_cell->children.at(0)->type == AST_CELLTYPE);
1048  new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str.c_str());
1049  }
1050  }
1051 
1052  goto apply_newNode;
1053  }
1054 
1055  // replace primitives with assignmens
1056  if (type == AST_PRIMITIVE)
1057  {
1058  if (children.size() < 2)
1059  log_error("Insufficient number of arguments for primitive `%s' at %s:%d!\n",
1060  str.c_str(), filename.c_str(), linenum);
1061 
1062  std::vector<AstNode*> children_list;
1063  for (auto child : children) {
1064  log_assert(child->type == AST_ARGUMENT);
1065  log_assert(child->children.size() == 1);
1066  children_list.push_back(child->children[0]);
1067  child->children.clear();
1068  delete child;
1069  }
1070  children.clear();
1071 
1072  if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1")
1073  {
1074  if (children_list.size() != 3)
1075  log_error("Invalid number of arguments for primitive `%s' at %s:%d!\n",
1076  str.c_str(), filename.c_str(), linenum);
1077 
1078  std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz);
1079 
1080  AstNode *mux_input = children_list.at(1);
1081  if (str == "notif0" || str == "notif1") {
1082  mux_input = new AstNode(AST_BIT_NOT, mux_input);
1083  }
1084  AstNode *node = new AstNode(AST_TERNARY, children_list.at(2));
1085  if (str == "bufif0") {
1086  node->children.push_back(AstNode::mkconst_bits(z_const, false));
1087  node->children.push_back(mux_input);
1088  } else {
1089  node->children.push_back(mux_input);
1090  node->children.push_back(AstNode::mkconst_bits(z_const, false));
1091  }
1092 
1093  str.clear();
1094  type = AST_ASSIGN;
1095  children.push_back(children_list.at(0));
1096  children.push_back(node);
1097  did_something = true;
1098  }
1099  else
1100  {
1101  AstNodeType op_type = AST_NONE;
1102  bool invert_results = false;
1103 
1104  if (str == "and")
1105  op_type = AST_BIT_AND;
1106  if (str == "nand")
1107  op_type = AST_BIT_AND, invert_results = true;
1108  if (str == "or")
1109  op_type = AST_BIT_OR;
1110  if (str == "nor")
1111  op_type = AST_BIT_OR, invert_results = true;
1112  if (str == "xor")
1113  op_type = AST_BIT_XOR;
1114  if (str == "xnor")
1115  op_type = AST_BIT_XOR, invert_results = true;
1116  if (str == "buf")
1117  op_type = AST_POS;
1118  if (str == "not")
1119  op_type = AST_POS, invert_results = true;
1120  log_assert(op_type != AST_NONE);
1121 
1122  AstNode *node = children_list[1];
1123  if (op_type != AST_POS)
1124  for (size_t i = 2; i < children_list.size(); i++)
1125  node = new AstNode(op_type, node, children_list[i]);
1126  if (invert_results)
1127  node = new AstNode(AST_BIT_NOT, node);
1128 
1129  str.clear();
1130  type = AST_ASSIGN;
1131  children.push_back(children_list[0]);
1132  children.push_back(node);
1133  did_something = true;
1134  }
1135  }
1136 
1137  // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
1138  // a big case block that selects the correct single-bit assignment.
1139  if (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) {
1140  if (children[0]->type != AST_IDENTIFIER || children[0]->children.size() == 0)
1141  goto skip_dynamic_range_lvalue_expansion;
1142  if (children[0]->children[0]->range_valid || did_something)
1143  goto skip_dynamic_range_lvalue_expansion;
1144  if (children[0]->id2ast == NULL || children[0]->id2ast->type != AST_WIRE)
1145  goto skip_dynamic_range_lvalue_expansion;
1146  if (!children[0]->id2ast->range_valid)
1147  goto skip_dynamic_range_lvalue_expansion;
1148  int source_width = children[0]->id2ast->range_left - children[0]->id2ast->range_right + 1;
1149  int result_width = 1;
1150  AstNode *shift_expr = NULL;
1151  AstNode *range = children[0]->children[0];
1152  if (range->children.size() == 1) {
1153  shift_expr = range->children[0]->clone();
1154  } else {
1155  shift_expr = range->children[1]->clone();
1156  AstNode *left_at_zero_ast = range->children[0]->clone();
1157  AstNode *right_at_zero_ast = range->children[1]->clone();
1158  while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
1159  while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
1160  if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
1161  log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
1162  str.c_str(), filename.c_str(), linenum);
1163  result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
1164  }
1165  did_something = true;
1166  newNode = new AstNode(AST_CASE, shift_expr);
1167  for (int i = 0; i <= source_width-result_width; i++) {
1168  int start_bit = children[0]->id2ast->range_right + i;
1169  AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true));
1170  AstNode *lvalue = children[0]->clone();
1171  lvalue->delete_children();
1172  lvalue->children.push_back(new AstNode(AST_RANGE,
1173  mkconst_int(start_bit+result_width-1, true), mkconst_int(start_bit, true)));
1174  cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone())));
1175  newNode->children.push_back(cond);
1176  }
1177  goto apply_newNode;
1178  }
1179 skip_dynamic_range_lvalue_expansion:;
1180 
1181  if (stage > 1 && type == AST_ASSERT && current_block != NULL)
1182  {
1183  std::stringstream sstr;
1184  sstr << "$assert$" << filename << ":" << linenum << "$" << (autoidx++);
1185  std::string id_check = sstr.str() + "_CHECK", id_en = sstr.str() + "_EN";
1186 
1187  AstNode *wire_check = new AstNode(AST_WIRE);
1188  wire_check->str = id_check;
1189  current_ast_mod->children.push_back(wire_check);
1190  current_scope[wire_check->str] = wire_check;
1191  while (wire_check->simplify(true, false, false, 1, -1, false, false)) { }
1192 
1193  AstNode *wire_en = new AstNode(AST_WIRE);
1194  wire_en->str = id_en;
1195  current_ast_mod->children.push_back(wire_en);
1197  current_ast_mod->children.back()->children[0]->children[0]->children[0]->str = id_en;
1198  current_scope[wire_en->str] = wire_en;
1199  while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
1200 
1201  std::vector<RTLIL::State> x_bit;
1202  x_bit.push_back(RTLIL::State::Sx);
1203 
1204  AstNode *assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bit, false));
1205  assign_check->children[0]->str = id_check;
1206 
1207  AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, 1));
1208  assign_en->children[0]->str = id_en;
1209 
1210  AstNode *default_signals = new AstNode(AST_BLOCK);
1211  default_signals->children.push_back(assign_check);
1212  default_signals->children.push_back(assign_en);
1213  current_top_block->children.insert(current_top_block->children.begin(), default_signals);
1214 
1215  assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_REDUCE_BOOL, children[0]->clone()));
1216  assign_check->children[0]->str = id_check;
1217 
1218  assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(1, false, 1));
1219  assign_en->children[0]->str = id_en;
1220 
1221  newNode = new AstNode(AST_BLOCK);
1222  newNode->children.push_back(assign_check);
1223  newNode->children.push_back(assign_en);
1224 
1225  AstNode *assertnode = new AstNode(AST_ASSERT);
1226  assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
1227  assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
1228  assertnode->children[0]->str = id_check;
1229  assertnode->children[1]->str = id_en;
1230  assertnode->attributes.swap(attributes);
1231  current_ast_mod->children.push_back(assertnode);
1232 
1233  goto apply_newNode;
1234  }
1235 
1236  if (stage > 1 && type == AST_ASSERT && children.size() == 1)
1237  {
1238  children[0] = new AstNode(AST_REDUCE_BOOL, children[0]->clone());
1239  children.push_back(mkconst_int(1, false, 1));
1240  did_something = true;
1241  }
1242 
1243  // found right-hand side identifier for memory -> replace with memory read port
1244  if (stage > 1 && type == AST_IDENTIFIER && id2ast != NULL && id2ast->type == AST_MEMORY && !in_lvalue &&
1245  children[0]->type == AST_RANGE && children[0]->children.size() == 1) {
1246  newNode = new AstNode(AST_MEMRD, children[0]->children[0]->clone());
1247  newNode->str = str;
1248  newNode->id2ast = id2ast;
1249  goto apply_newNode;
1250  }
1251 
1252  // assignment with memory in left-hand side expression -> replace with memory write port
1253  if (stage > 1 && (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) && children[0]->type == AST_IDENTIFIER &&
1254  children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY && children[0]->id2ast->children.size() >= 2 &&
1255  children[0]->id2ast->children[0]->range_valid && children[0]->id2ast->children[1]->range_valid &&
1256  (children[0]->children.size() == 1 || children[0]->children.size() == 2) && children[0]->children[0]->type == AST_RANGE)
1257  {
1258  std::stringstream sstr;
1259  sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
1260  std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN";
1261 
1262  if (type == AST_ASSIGN_EQ)
1263  log_warning("Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n",
1264  filename.c_str(), linenum);
1265 
1266  int mem_width, mem_size, addr_bits;
1267  children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
1268 
1269  AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
1270  wire_addr->str = id_addr;
1271  current_ast_mod->children.push_back(wire_addr);
1272  current_scope[wire_addr->str] = wire_addr;
1273  while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
1274 
1275  AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
1276  wire_data->str = id_data;
1277  current_ast_mod->children.push_back(wire_data);
1278  current_scope[wire_data->str] = wire_data;
1279  while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
1280 
1281  AstNode *wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
1282  wire_en->str = id_en;
1283  current_ast_mod->children.push_back(wire_en);
1284  current_scope[wire_en->str] = wire_en;
1285  while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
1286 
1287  std::vector<RTLIL::State> x_bits_addr, x_bits_data, set_bits_en;
1288  for (int i = 0; i < addr_bits; i++)
1289  x_bits_addr.push_back(RTLIL::State::Sx);
1290  for (int i = 0; i < mem_width; i++)
1291  x_bits_data.push_back(RTLIL::State::Sx);
1292  for (int i = 0; i < mem_width; i++)
1293  set_bits_en.push_back(RTLIL::State::S1);
1294 
1295  AstNode *assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false));
1296  assign_addr->children[0]->str = id_addr;
1297 
1298  AstNode *assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false));
1299  assign_data->children[0]->str = id_data;
1300 
1301  AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width));
1302  assign_en->children[0]->str = id_en;
1303 
1304  AstNode *default_signals = new AstNode(AST_BLOCK);
1305  default_signals->children.push_back(assign_addr);
1306  default_signals->children.push_back(assign_data);
1307  default_signals->children.push_back(assign_en);
1308  current_top_block->children.insert(current_top_block->children.begin(), default_signals);
1309 
1310  assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
1311  assign_addr->children[0]->str = id_addr;
1312 
1313  if (children[0]->children.size() == 2)
1314  {
1315  if (children[0]->children[1]->range_valid)
1316  {
1317  int offset = children[0]->children[1]->range_right;
1318  int width = children[0]->children[1]->range_left - offset + 1;
1319 
1320  std::vector<RTLIL::State> padding_x(offset, RTLIL::State::Sx);
1321 
1322  for (int i = 0; i < mem_width; i++)
1323  set_bits_en[i] = offset <= i && i < offset+width ? RTLIL::State::S1 : RTLIL::State::S0;
1324 
1325  assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
1326  new AstNode(AST_CONCAT, mkconst_bits(padding_x, false), children[1]->clone()));
1327  assign_data->children[0]->str = id_data;
1328 
1329  assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
1330  assign_en->children[0]->str = id_en;
1331  }
1332  else
1333  {
1334  AstNode *the_range = children[0]->children[1];
1335  AstNode *left_at_zero_ast = the_range->children[0]->clone();
1336  AstNode *right_at_zero_ast = the_range->children.size() >= 2 ? the_range->children[1]->clone() : left_at_zero_ast->clone();
1337  AstNode *offset_ast = right_at_zero_ast->clone();
1338 
1339  while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
1340  while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
1341  if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
1342  log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
1343  int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
1344 
1345  for (int i = 0; i < mem_width; i++)
1346  set_bits_en[i] = i < width ? RTLIL::State::S1 : RTLIL::State::S0;
1347 
1348  assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
1349  new AstNode(AST_SHIFT_LEFT, children[1]->clone(), offset_ast->clone()));
1350  assign_data->children[0]->str = id_data;
1351 
1352  assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
1353  new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone()));
1354  assign_en->children[0]->str = id_en;
1355 
1356  delete left_at_zero_ast;
1357  delete right_at_zero_ast;
1358  delete offset_ast;
1359  }
1360  }
1361  else
1362  {
1363  assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone());
1364  assign_data->children[0]->str = id_data;
1365 
1366  assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
1367  assign_en->children[0]->str = id_en;
1368  }
1369 
1370  newNode = new AstNode(AST_BLOCK);
1371  newNode->children.push_back(assign_addr);
1372  newNode->children.push_back(assign_data);
1373  newNode->children.push_back(assign_en);
1374 
1375  AstNode *wrnode = new AstNode(AST_MEMWR);
1376  wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
1377  wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
1378  wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
1379  wrnode->str = children[0]->str;
1380  wrnode->children[0]->str = id_addr;
1381  wrnode->children[1]->str = id_data;
1382  wrnode->children[2]->str = id_en;
1383  current_ast_mod->children.push_back(wrnode);
1384 
1385  goto apply_newNode;
1386  }
1387 
1388  // replace function and task calls with the code from the function or task
1389  if ((type == AST_FCALL || type == AST_TCALL) && !str.empty())
1390  {
1391  if (type == AST_FCALL)
1392  {
1393  if (str == "\\$clog2")
1394  {
1395  if (children.size() != 1)
1396  log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
1397  RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
1398 
1399  AstNode *buf = children[0]->clone();
1400  while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1401  if (buf->type != AST_CONSTANT)
1402  log_error("Failed to evaluate system function `%s' with non-constant value at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1403 
1404  RTLIL::Const arg_value = buf->bitsAsConst();
1405  if (arg_value.as_bool())
1406  arg_value = const_sub(arg_value, 1, false, false, GetSize(arg_value));
1407  delete buf;
1408 
1409  uint32_t result = 0;
1410  for (size_t i = 0; i < arg_value.bits.size(); i++)
1411  if (arg_value.bits.at(i) == RTLIL::State::S1)
1412  result = i + 1;
1413 
1414  newNode = mkconst_int(result, false);
1415  goto apply_newNode;
1416  }
1417 
1418  if (str == "\\$ln" || str == "\\$log10" || str == "\\$exp" || str == "\\$sqrt" || str == "\\$pow" ||
1419  str == "\\$floor" || str == "\\$ceil" || str == "\\$sin" || str == "\\$cos" || str == "\\$tan" ||
1420  str == "\\$asin" || str == "\\$acos" || str == "\\$atan" || str == "\\$atan2" || str == "\\$hypot" ||
1421  str == "\\$sinh" || str == "\\$cosh" || str == "\\$tanh" || str == "\\$asinh" || str == "\\$acosh" || str == "\\$atanh")
1422  {
1423  bool func_with_two_arguments = str == "\\$pow" || str == "\\$atan2" || str == "\\$hypot";
1424  double x = 0, y = 0;
1425 
1426  if (func_with_two_arguments) {
1427  if (children.size() != 2)
1428  log_error("System function %s got %d arguments, expected 2 at %s:%d.\n",
1429  RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
1430  } else {
1431  if (children.size() != 1)
1432  log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
1433  RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
1434  }
1435 
1436  if (children.size() >= 1) {
1437  while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1438  if (!children[0]->isConst())
1439  log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
1440  RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
1441  int child_width_hint = width_hint;
1442  bool child_sign_hint = sign_hint;
1443  children[0]->detectSignWidth(child_width_hint, child_sign_hint);
1444  x = children[0]->asReal(child_sign_hint);
1445  }
1446 
1447  if (children.size() >= 2) {
1448  while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1449  if (!children[1]->isConst())
1450  log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
1451  RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
1452  int child_width_hint = width_hint;
1453  bool child_sign_hint = sign_hint;
1454  children[1]->detectSignWidth(child_width_hint, child_sign_hint);
1455  y = children[1]->asReal(child_sign_hint);
1456  }
1457 
1458  newNode = new AstNode(AST_REALVALUE);
1459  if (str == "\\$ln") newNode->realvalue = ::log(x);
1460  else if (str == "\\$log10") newNode->realvalue = ::log10(x);
1461  else if (str == "\\$exp") newNode->realvalue = ::exp(x);
1462  else if (str == "\\$sqrt") newNode->realvalue = ::sqrt(x);
1463  else if (str == "\\$pow") newNode->realvalue = ::pow(x, y);
1464  else if (str == "\\$floor") newNode->realvalue = ::floor(x);
1465  else if (str == "\\$ceil") newNode->realvalue = ::ceil(x);
1466  else if (str == "\\$sin") newNode->realvalue = ::sin(x);
1467  else if (str == "\\$cos") newNode->realvalue = ::cos(x);
1468  else if (str == "\\$tan") newNode->realvalue = ::tan(x);
1469  else if (str == "\\$asin") newNode->realvalue = ::asin(x);
1470  else if (str == "\\$acos") newNode->realvalue = ::acos(x);
1471  else if (str == "\\$atan") newNode->realvalue = ::atan(x);
1472  else if (str == "\\$atan2") newNode->realvalue = ::atan2(x, y);
1473  else if (str == "\\$hypot") newNode->realvalue = ::hypot(x, y);
1474  else if (str == "\\$sinh") newNode->realvalue = ::sinh(x);
1475  else if (str == "\\$cosh") newNode->realvalue = ::cosh(x);
1476  else if (str == "\\$tanh") newNode->realvalue = ::tanh(x);
1477  else if (str == "\\$asinh") newNode->realvalue = ::asinh(x);
1478  else if (str == "\\$acosh") newNode->realvalue = ::acosh(x);
1479  else if (str == "\\$atanh") newNode->realvalue = ::atanh(x);
1480  else log_abort();
1481  goto apply_newNode;
1482  }
1483 
1484  if (current_scope.count(str) != 0 && current_scope[str]->type == AST_DPI_FUNCTION)
1485  {
1486  AstNode *dpi_decl = current_scope[str];
1487 
1488  std::string rtype, fname;
1489  std::vector<std::string> argtypes;
1490  std::vector<AstNode*> args;
1491 
1492  rtype = RTLIL::unescape_id(dpi_decl->children.at(0)->str);
1493  fname = RTLIL::unescape_id(dpi_decl->children.at(1)->str);
1494 
1495  for (int i = 2; i < GetSize(dpi_decl->children); i++)
1496  {
1497  if (i-2 >= GetSize(children))
1498  log_error("Insufficient number of arguments in DPI function call at %s:%d.\n", filename.c_str(), linenum);
1499 
1500  argtypes.push_back(RTLIL::unescape_id(dpi_decl->children.at(i)->str));
1501  args.push_back(children.at(i-2)->clone());
1502  while (args.back()->simplify(true, false, false, stage, -1, false, true)) { }
1503 
1504  if (args.back()->type != AST_CONSTANT && args.back()->type != AST_REALVALUE)
1505  log_error("Failed to evaluate DPI function with non-constant argument at %s:%d.\n", filename.c_str(), linenum);
1506  }
1507 
1508  newNode = dpi_call(rtype, fname, argtypes, args);
1509 
1510  for (auto arg : args)
1511  delete arg;
1512 
1513  goto apply_newNode;
1514  }
1515 
1516  if (current_scope.count(str) == 0 || current_scope[str]->type != AST_FUNCTION)
1517  log_error("Can't resolve function name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1518  }
1519  if (type == AST_TCALL) {
1520  if (str == "\\$readmemh" || str == "\\$readmemb")
1521  {
1522  if (GetSize(children) < 2 || GetSize(children) > 4)
1523  log_error("System function %s got %d arguments, expected 2-4 at %s:%d.\n",
1524  RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
1525 
1526  AstNode *node_filename = children[0]->clone();
1527  while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1528  if (node_filename->type != AST_CONSTANT)
1529  log_error("Failed to evaluate system function `%s' with non-constant 1st argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1530 
1531  AstNode *node_memory = children[1]->clone();
1532  while (node_memory->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1533  if (node_memory->type != AST_IDENTIFIER || node_memory->id2ast == nullptr || node_memory->id2ast->type != AST_MEMORY)
1534  log_error("Failed to evaluate system function `%s' with non-memory 2nd argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1535 
1536  int start_addr = -1, finish_addr = -1;
1537 
1538  if (GetSize(children) > 2) {
1539  AstNode *node_addr = children[2]->clone();
1540  while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1541  if (node_addr->type != AST_CONSTANT)
1542  log_error("Failed to evaluate system function `%s' with non-constant 3rd argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1543  start_addr = node_addr->asInt(false);
1544  }
1545 
1546  if (GetSize(children) > 3) {
1547  AstNode *node_addr = children[3]->clone();
1548  while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1549  if (node_addr->type != AST_CONSTANT)
1550  log_error("Failed to evaluate system function `%s' with non-constant 4th argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1551  finish_addr = node_addr->asInt(false);
1552  }
1553 
1554  newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr);
1555  goto apply_newNode;
1556  }
1557 
1558  if (current_scope.count(str) == 0 || current_scope[str]->type != AST_TASK)
1559  log_error("Can't resolve task name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1560  }
1561 
1562  AstNode *decl = current_scope[str];
1563 
1564  std::stringstream sstr;
1565  sstr << "$func$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++) << "$";
1566  std::string prefix = sstr.str();
1567 
1568  bool recommend_const_eval = false;
1569  bool require_const_eval = in_param ? false : has_const_only_constructs(recommend_const_eval);
1570  if ((in_param || recommend_const_eval || require_const_eval) && !decl->attributes.count("\\via_celltype"))
1571  {
1572  bool all_args_const = true;
1573  for (auto child : children) {
1574  while (child->simplify(true, false, false, 1, -1, false, true)) { }
1575  if (child->type != AST_CONSTANT)
1576  all_args_const = false;
1577  }
1578 
1579  if (all_args_const) {
1580  AstNode *func_workspace = current_scope[str]->clone();
1581  newNode = func_workspace->eval_const_function(this);
1582  delete func_workspace;
1583  goto apply_newNode;
1584  }
1585 
1586  if (in_param)
1587  log_error("Non-constant function call in constant expression at %s:%d.\n", filename.c_str(), linenum);
1588  if (require_const_eval)
1589  log_error("Function %s can only be called with constant arguments at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1590  }
1591 
1592  size_t arg_count = 0;
1593  std::map<std::string, std::string> replace_rules;
1594 
1595  if (current_block == NULL)
1596  {
1597  log_assert(type == AST_FCALL);
1598 
1599  AstNode *wire = NULL;
1600  for (auto child : decl->children)
1601  if (child->type == AST_WIRE && child->str == str)
1602  wire = child->clone();
1603  log_assert(wire != NULL);
1604 
1605  wire->str = prefix + str;
1606  wire->port_id = 0;
1607  wire->is_input = false;
1608  wire->is_output = false;
1609 
1610  current_ast_mod->children.push_back(wire);
1611  while (wire->simplify(true, false, false, 1, -1, false, false)) { }
1612 
1613  AstNode *lvalue = new AstNode(AST_IDENTIFIER);
1614  lvalue->str = wire->str;
1615 
1616  AstNode *always = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK,
1617  new AstNode(AST_ASSIGN_EQ, lvalue, clone())));
1618  current_ast_mod->children.push_back(always);
1619 
1620  goto replace_fcall_with_id;
1621  }
1622 
1623  if (decl->attributes.count("\\via_celltype"))
1624  {
1625  std::string celltype = decl->attributes.at("\\via_celltype")->asAttrConst().decode_string();
1626  std::string outport = str;
1627 
1628  if (celltype.find(' ') != std::string::npos) {
1629  int pos = celltype.find(' ');
1630  outport = RTLIL::escape_id(celltype.substr(pos+1));
1631  celltype = RTLIL::escape_id(celltype.substr(0, pos));
1632  } else
1633  celltype = RTLIL::escape_id(celltype);
1634 
1635  AstNode *cell = new AstNode(AST_CELL, new AstNode(AST_CELLTYPE));
1636  cell->str = prefix.substr(0, GetSize(prefix)-1);
1637  cell->children[0]->str = celltype;
1638 
1639  for (auto attr : decl->attributes)
1640  if (attr.first.str().rfind("\\via_celltype_defparam_", 0) == 0)
1641  {
1642  AstNode *cell_arg = new AstNode(AST_PARASET, attr.second->clone());
1643  cell_arg->str = RTLIL::escape_id(attr.first.str().substr(strlen("\\via_celltype_defparam_")));
1644  cell->children.push_back(cell_arg);
1645  }
1646 
1647  for (auto child : decl->children)
1648  if (child->type == AST_WIRE && (child->is_input || child->is_output || (type == AST_FCALL && child->str == str)))
1649  {
1650  AstNode *wire = child->clone();
1651  wire->str = prefix + wire->str;
1652  wire->port_id = 0;
1653  wire->is_input = false;
1654  wire->is_output = false;
1655  current_ast_mod->children.push_back(wire);
1656  while (wire->simplify(true, false, false, 1, -1, false, false)) { }
1657 
1658  AstNode *wire_id = new AstNode(AST_IDENTIFIER);
1659  wire_id->str = wire->str;
1660 
1661  if ((child->is_input || child->is_output) && arg_count < children.size())
1662  {
1663  AstNode *arg = children[arg_count++]->clone();
1664  AstNode *assign = child->is_input ?
1665  new AstNode(AST_ASSIGN_EQ, wire_id->clone(), arg) :
1666  new AstNode(AST_ASSIGN_EQ, arg, wire_id->clone());
1667 
1668  for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
1669  if (*it != current_block_child)
1670  continue;
1671  current_block->children.insert(it, assign);
1672  break;
1673  }
1674  }
1675 
1676  AstNode *cell_arg = new AstNode(AST_ARGUMENT, wire_id);
1677  cell_arg->str = child->str == str ? outport : child->str;
1678  cell->children.push_back(cell_arg);
1679  }
1680 
1681  current_ast_mod->children.push_back(cell);
1682  goto replace_fcall_with_id;
1683  }
1684 
1685  for (auto child : decl->children)
1686  if (child->type == AST_WIRE)
1687  {
1688  AstNode *wire = child->clone();
1689  wire->str = prefix + wire->str;
1690  wire->port_id = 0;
1691  wire->is_input = false;
1692  wire->is_output = false;
1693  current_ast_mod->children.push_back(wire);
1694  while (wire->simplify(true, false, false, 1, -1, false, false)) { }
1695 
1696  replace_rules[child->str] = wire->str;
1697 
1698  if ((child->is_input || child->is_output) && arg_count < children.size())
1699  {
1700  AstNode *arg = children[arg_count++]->clone();
1701  AstNode *wire_id = new AstNode(AST_IDENTIFIER);
1702  wire_id->str = wire->str;
1703  AstNode *assign = child->is_input ?
1704  new AstNode(AST_ASSIGN_EQ, wire_id, arg) :
1705  new AstNode(AST_ASSIGN_EQ, arg, wire_id);
1706 
1707  for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
1708  if (*it != current_block_child)
1709  continue;
1710  current_block->children.insert(it, assign);
1711  break;
1712  }
1713  }
1714  }
1715 
1716  for (auto child : decl->children)
1717  if (child->type != AST_WIRE)
1718  {
1719  AstNode *stmt = child->clone();
1720  stmt->replace_ids(prefix, replace_rules);
1721 
1722  for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
1723  if (*it != current_block_child)
1724  continue;
1725  current_block->children.insert(it, stmt);
1726  break;
1727  }
1728  }
1729 
1730  replace_fcall_with_id:
1731  if (type == AST_FCALL) {
1732  delete_children();
1733  type = AST_IDENTIFIER;
1734  str = prefix + str;
1735  }
1736  if (type == AST_TCALL)
1737  str = "";
1738  did_something = true;
1739  }
1740 
1741  // perform const folding when activated
1742  if (const_fold)
1743  {
1744  bool string_op;
1745  std::vector<RTLIL::State> tmp_bits;
1746  RTLIL::Const (*const_func)(const RTLIL::Const&, const RTLIL::Const&, bool, bool, int);
1747  RTLIL::Const dummy_arg;
1748 
1749  switch (type)
1750  {
1751  case AST_IDENTIFIER:
1752  if (current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM)) {
1753  if (current_scope[str]->children[0]->type == AST_CONSTANT) {
1754  if (children.size() != 0 && children[0]->type == AST_RANGE && children[0]->range_valid) {
1755  std::vector<RTLIL::State> data;
1756  bool param_upto = current_scope[str]->range_valid && current_scope[str]->range_swapped;
1757  int param_offset = current_scope[str]->range_valid ? current_scope[str]->range_right : 0;
1758  int param_width = current_scope[str]->range_valid ? current_scope[str]->range_left - current_scope[str]->range_right + 1 :
1759  GetSize(current_scope[str]->children[0]->bits);
1760  int tmp_range_left = children[0]->range_left, tmp_range_right = children[0]->range_right;
1761  if (param_upto) {
1762  tmp_range_left = (param_width + 2*param_offset) - children[0]->range_right - 1;
1763  tmp_range_right = (param_width + 2*param_offset) - children[0]->range_left - 1;
1764  }
1765  for (int i = tmp_range_right; i <= tmp_range_left; i++) {
1766  int index = i - param_offset;
1767  if (0 <= index && index < param_width)
1768  data.push_back(current_scope[str]->children[0]->bits[index]);
1769  else
1770  data.push_back(RTLIL::State::Sx);
1771  }
1772  newNode = mkconst_bits(data, false);
1773  } else
1774  if (children.size() == 0)
1775  newNode = current_scope[str]->children[0]->clone();
1776  } else
1777  if (current_scope[str]->children[0]->isConst())
1778  newNode = current_scope[str]->children[0]->clone();
1779  }
1780  else if (at_zero && current_scope.count(str) > 0 && (current_scope[str]->type == AST_WIRE || current_scope[str]->type == AST_AUTOWIRE)) {
1781  newNode = mkconst_int(0, sign_hint, width_hint);
1782  }
1783  break;
1784  case AST_BIT_NOT:
1785  if (children[0]->type == AST_CONSTANT) {
1786  RTLIL::Const y = RTLIL::const_not(children[0]->bitsAsConst(width_hint, sign_hint), dummy_arg, sign_hint, false, width_hint);
1787  newNode = mkconst_bits(y.bits, sign_hint);
1788  }
1789  break;
1790  case AST_TO_SIGNED:
1791  case AST_TO_UNSIGNED:
1792  if (children[0]->type == AST_CONSTANT) {
1793  RTLIL::Const y = children[0]->bitsAsConst(width_hint, sign_hint);
1794  newNode = mkconst_bits(y.bits, type == AST_TO_SIGNED);
1795  }
1796  break;
1797  if (0) { case AST_BIT_AND: const_func = RTLIL::const_and; }
1798  if (0) { case AST_BIT_OR: const_func = RTLIL::const_or; }
1799  if (0) { case AST_BIT_XOR: const_func = RTLIL::const_xor; }
1800  if (0) { case AST_BIT_XNOR: const_func = RTLIL::const_xnor; }
1801  if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
1802  RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
1803  children[1]->bitsAsConst(width_hint, sign_hint), sign_hint, sign_hint, width_hint);
1804  newNode = mkconst_bits(y.bits, sign_hint);
1805  }
1806  break;
1807  if (0) { case AST_REDUCE_AND: const_func = RTLIL::const_reduce_and; }
1808  if (0) { case AST_REDUCE_OR: const_func = RTLIL::const_reduce_or; }
1809  if (0) { case AST_REDUCE_XOR: const_func = RTLIL::const_reduce_xor; }
1810  if (0) { case AST_REDUCE_XNOR: const_func = RTLIL::const_reduce_xnor; }
1811  if (0) { case AST_REDUCE_BOOL: const_func = RTLIL::const_reduce_bool; }
1812  if (children[0]->type == AST_CONSTANT) {
1813  RTLIL::Const y = const_func(RTLIL::Const(children[0]->bits), dummy_arg, false, false, -1);
1814  newNode = mkconst_bits(y.bits, false);
1815  }
1816  break;
1817  case AST_LOGIC_NOT:
1818  if (children[0]->type == AST_CONSTANT) {
1819  RTLIL::Const y = RTLIL::const_logic_not(RTLIL::Const(children[0]->bits), dummy_arg, children[0]->is_signed, false, -1);
1820  newNode = mkconst_bits(y.bits, false);
1821  } else
1822  if (children[0]->isConst()) {
1823  newNode = mkconst_int(children[0]->asReal(sign_hint) == 0, false, 1);
1824  }
1825  break;
1826  if (0) { case AST_LOGIC_AND: const_func = RTLIL::const_logic_and; }
1827  if (0) { case AST_LOGIC_OR: const_func = RTLIL::const_logic_or; }
1828  if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
1829  RTLIL::Const y = const_func(RTLIL::Const(children[0]->bits), RTLIL::Const(children[1]->bits),
1830  children[0]->is_signed, children[1]->is_signed, -1);
1831  newNode = mkconst_bits(y.bits, false);
1832  } else
1833  if (children[0]->isConst() && children[1]->isConst()) {
1834  if (type == AST_LOGIC_AND)
1835  newNode = mkconst_int((children[0]->asReal(sign_hint) != 0) && (children[1]->asReal(sign_hint) != 0), false, 1);
1836  else
1837  newNode = mkconst_int((children[0]->asReal(sign_hint) != 0) || (children[1]->asReal(sign_hint) != 0), false, 1);
1838  }
1839  break;
1840  if (0) { case AST_SHIFT_LEFT: const_func = RTLIL::const_shl; }
1841  if (0) { case AST_SHIFT_RIGHT: const_func = RTLIL::const_shr; }
1842  if (0) { case AST_SHIFT_SLEFT: const_func = RTLIL::const_sshl; }
1843  if (0) { case AST_SHIFT_SRIGHT: const_func = RTLIL::const_sshr; }
1844  if (0) { case AST_POW: const_func = RTLIL::const_pow; }
1845  if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
1846  RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
1847  RTLIL::Const(children[1]->bits), sign_hint, type == AST_POW ? children[1]->is_signed : false, width_hint);
1848  newNode = mkconst_bits(y.bits, sign_hint);
1849  } else
1850  if (type == AST_POW && children[0]->isConst() && children[1]->isConst()) {
1851  newNode = new AstNode(AST_REALVALUE);
1852  newNode->realvalue = pow(children[0]->asReal(sign_hint), children[1]->asReal(sign_hint));
1853  }
1854  break;
1855  if (0) { case AST_LT: const_func = RTLIL::const_lt; }
1856  if (0) { case AST_LE: const_func = RTLIL::const_le; }
1857  if (0) { case AST_EQ: const_func = RTLIL::const_eq; }
1858  if (0) { case AST_NE: const_func = RTLIL::const_ne; }
1859  if (0) { case AST_EQX: const_func = RTLIL::const_eqx; }
1860  if (0) { case AST_NEX: const_func = RTLIL::const_nex; }
1861  if (0) { case AST_GE: const_func = RTLIL::const_ge; }
1862  if (0) { case AST_GT: const_func = RTLIL::const_gt; }
1863  if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
1864  int cmp_width = std::max(children[0]->bits.size(), children[1]->bits.size());
1865  bool cmp_signed = children[0]->is_signed && children[1]->is_signed;
1866  RTLIL::Const y = const_func(children[0]->bitsAsConst(cmp_width, cmp_signed),
1867  children[1]->bitsAsConst(cmp_width, cmp_signed), cmp_signed, cmp_signed, 1);
1868  newNode = mkconst_bits(y.bits, false);
1869  } else
1870  if (children[0]->isConst() && children[1]->isConst()) {
1871  bool cmp_signed = (children[0]->type == AST_REALVALUE || children[0]->is_signed) && (children[1]->type == AST_REALVALUE || children[1]->is_signed);
1872  switch (type) {
1873  case AST_LT: newNode = mkconst_int(children[0]->asReal(cmp_signed) < children[1]->asReal(cmp_signed), false, 1); break;
1874  case AST_LE: newNode = mkconst_int(children[0]->asReal(cmp_signed) <= children[1]->asReal(cmp_signed), false, 1); break;
1875  case AST_EQ: newNode = mkconst_int(children[0]->asReal(cmp_signed) == children[1]->asReal(cmp_signed), false, 1); break;
1876  case AST_NE: newNode = mkconst_int(children[0]->asReal(cmp_signed) != children[1]->asReal(cmp_signed), false, 1); break;
1877  case AST_EQX: newNode = mkconst_int(children[0]->asReal(cmp_signed) == children[1]->asReal(cmp_signed), false, 1); break;
1878  case AST_NEX: newNode = mkconst_int(children[0]->asReal(cmp_signed) != children[1]->asReal(cmp_signed), false, 1); break;
1879  case AST_GE: newNode = mkconst_int(children[0]->asReal(cmp_signed) >= children[1]->asReal(cmp_signed), false, 1); break;
1880  case AST_GT: newNode = mkconst_int(children[0]->asReal(cmp_signed) > children[1]->asReal(cmp_signed), false, 1); break;
1881  default: log_abort();
1882  }
1883  }
1884  break;
1885  if (0) { case AST_ADD: const_func = RTLIL::const_add; }
1886  if (0) { case AST_SUB: const_func = RTLIL::const_sub; }
1887  if (0) { case AST_MUL: const_func = RTLIL::const_mul; }
1888  if (0) { case AST_DIV: const_func = RTLIL::const_div; }
1889  if (0) { case AST_MOD: const_func = RTLIL::const_mod; }
1890  if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
1891  RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
1892  children[1]->bitsAsConst(width_hint, sign_hint), sign_hint, sign_hint, width_hint);
1893  newNode = mkconst_bits(y.bits, sign_hint);
1894  } else
1895  if (children[0]->isConst() && children[1]->isConst()) {
1896  newNode = new AstNode(AST_REALVALUE);
1897  switch (type) {
1898  case AST_ADD: newNode->realvalue = children[0]->asReal(sign_hint) + children[1]->asReal(sign_hint); break;
1899  case AST_SUB: newNode->realvalue = children[0]->asReal(sign_hint) - children[1]->asReal(sign_hint); break;
1900  case AST_MUL: newNode->realvalue = children[0]->asReal(sign_hint) * children[1]->asReal(sign_hint); break;
1901  case AST_DIV: newNode->realvalue = children[0]->asReal(sign_hint) / children[1]->asReal(sign_hint); break;
1902  case AST_MOD: newNode->realvalue = fmod(children[0]->asReal(sign_hint), children[1]->asReal(sign_hint)); break;
1903  default: log_abort();
1904  }
1905  }
1906  break;
1907  if (0) { case AST_POS: const_func = RTLIL::const_pos; }
1908  if (0) { case AST_NEG: const_func = RTLIL::const_neg; }
1909  if (children[0]->type == AST_CONSTANT) {
1910  RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint), dummy_arg, sign_hint, false, width_hint);
1911  newNode = mkconst_bits(y.bits, sign_hint);
1912  } else
1913  if (children[0]->isConst()) {
1914  newNode = new AstNode(AST_REALVALUE);
1915  if (type == AST_POS)
1916  newNode->realvalue = +children[0]->asReal(sign_hint);
1917  else
1918  newNode->realvalue = -children[0]->asReal(sign_hint);
1919  }
1920  break;
1921  case AST_TERNARY:
1922  if (children[0]->isConst())
1923  {
1924  bool found_sure_true = false;
1925  bool found_maybe_true = false;
1926 
1927  if (children[0]->type == AST_CONSTANT)
1928  for (auto &bit : children[0]->bits) {
1929  if (bit == RTLIL::State::S1)
1930  found_sure_true = true;
1931  if (bit > RTLIL::State::S1)
1932  found_maybe_true = true;
1933  }
1934  else
1935  found_sure_true = children[0]->asReal(sign_hint) != 0;
1936 
1937  AstNode *choice = NULL, *not_choice = NULL;
1938  if (found_sure_true)
1939  choice = children[1], not_choice = children[2];
1940  else if (!found_maybe_true)
1941  choice = children[2], not_choice = children[1];
1942 
1943  if (choice != NULL) {
1944  if (choice->type == AST_CONSTANT) {
1945  int other_width_hint = width_hint;
1946  bool other_sign_hint = sign_hint, other_real = false;
1947  not_choice->detectSignWidth(other_width_hint, other_sign_hint, &other_real);
1948  if (other_real) {
1949  newNode = new AstNode(AST_REALVALUE);
1950  choice->detectSignWidth(width_hint, sign_hint);
1951  newNode->realvalue = choice->asReal(sign_hint);
1952  } else {
1953  RTLIL::Const y = choice->bitsAsConst(width_hint, sign_hint);
1954  if (choice->is_string && y.bits.size() % 8 == 0 && sign_hint == false)
1955  newNode = mkconst_str(y.bits);
1956  else
1957  newNode = mkconst_bits(y.bits, sign_hint);
1958  }
1959  } else
1960  if (choice->isConst()) {
1961  newNode = choice->clone();
1962  }
1963  } else if (children[1]->type == AST_CONSTANT && children[2]->type == AST_CONSTANT) {
1964  RTLIL::Const a = children[1]->bitsAsConst(width_hint, sign_hint);
1965  RTLIL::Const b = children[2]->bitsAsConst(width_hint, sign_hint);
1966  log_assert(a.bits.size() == b.bits.size());
1967  for (size_t i = 0; i < a.bits.size(); i++)
1968  if (a.bits[i] != b.bits[i])
1969  a.bits[i] = RTLIL::State::Sx;
1970  newNode = mkconst_bits(a.bits, sign_hint);
1971  } else if (children[1]->isConst() && children[2]->isConst()) {
1972  newNode = new AstNode(AST_REALVALUE);
1973  if (children[1]->asReal(sign_hint) == children[2]->asReal(sign_hint))
1974  newNode->realvalue = children[1]->asReal(sign_hint);
1975  else
1976  // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
1977  // the data type in question should be returned if the ?: is ambiguous. The
1978  // value in Table 7-1 for the 'real' type is 0.0.
1979  newNode->realvalue = 0.0;
1980  }
1981  }
1982  break;
1983  case AST_CONCAT:
1984  string_op = !children.empty();
1985  for (auto it = children.begin(); it != children.end(); it++) {
1986  if ((*it)->type != AST_CONSTANT)
1987  goto not_const;
1988  if (!(*it)->is_string)
1989  string_op = false;
1990  tmp_bits.insert(tmp_bits.end(), (*it)->bits.begin(), (*it)->bits.end());
1991  }
1992  newNode = string_op ? mkconst_str(tmp_bits) : mkconst_bits(tmp_bits, false);
1993  break;
1994  case AST_REPLICATE:
1995  if (children.at(0)->type != AST_CONSTANT || children.at(1)->type != AST_CONSTANT)
1996  goto not_const;
1997  for (int i = 0; i < children[0]->bitsAsConst().as_int(); i++)
1998  tmp_bits.insert(tmp_bits.end(), children.at(1)->bits.begin(), children.at(1)->bits.end());
1999  newNode = children.at(1)->is_string ? mkconst_str(tmp_bits) : mkconst_bits(tmp_bits, false);
2000  break;
2001  default:
2002  not_const:
2003  break;
2004  }
2005  }
2006 
2007  // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
2008  if (newNode) {
2009 apply_newNode:
2010  // fprintf(stderr, "----\n");
2011  // dumpAst(stderr, "- ");
2012  // newNode->dumpAst(stderr, "+ ");
2013  log_assert(newNode != NULL);
2014  newNode->filename = filename;
2015  newNode->linenum = linenum;
2016  newNode->cloneInto(this);
2017  delete newNode;
2018  did_something = true;
2019  }
2020 
2021  if (!did_something)
2022  basic_prep = true;
2023 
2024  return did_something;
2025 }
2026 
2027 static void replace_result_wire_name_in_function(AstNode *node, std::string &from, std::string &to)
2028 {
2029  for (auto &it : node->children)
2031  if (node->str == from)
2032  node->str = to;
2033 }
2034 
2035 // replace a readmem[bh] TCALL ast node with a block of memory assignments
2036 AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr)
2037 {
2038  AstNode *block = new AstNode(AST_BLOCK);
2039 
2040  std::ifstream f;
2041  f.open(mem_filename.c_str());
2042 
2043  if (f.fail())
2044  log_error("Can not open file `%s` for %s at %s:%d.\n", mem_filename.c_str(), str.c_str(), filename.c_str(), linenum);
2045 
2046  log_assert(GetSize(memory->children) == 2 && memory->children[1]->type == AST_RANGE && memory->children[1]->range_valid);
2047  int range_left = memory->children[1]->range_left, range_right = memory->children[1]->range_right;
2048  int range_min = std::min(range_left, range_right), range_max = std::max(range_left, range_right);
2049 
2050  if (start_addr < 0)
2051  start_addr = range_min;
2052 
2053  if (finish_addr < 0)
2054  finish_addr = range_max;
2055 
2056  bool in_comment = false;
2057  int increment = start_addr <= finish_addr ? +1 : -1;
2058  int cursor = start_addr;
2059 
2060  while (!f.eof())
2061  {
2062  std::string line, token;
2063  std::getline(f, line);
2064 
2065  for (int i = 0; i < GetSize(line); i++) {
2066  if (in_comment && line.substr(i, 2) == "*/") {
2067  line[i] = ' ';
2068  line[i+1] = ' ';
2069  in_comment = false;
2070  continue;
2071  }
2072  if (!in_comment && line.substr(i, 2) == "/*")
2073  in_comment = true;
2074  if (in_comment)
2075  line[i] = ' ';
2076  }
2077 
2078  while (1)
2079  {
2080  token = next_token(line, " \t\r\n");
2081  if (token.empty() || token.substr(0, 2) == "//")
2082  break;
2083 
2084  if (token[0] == '@') {
2085  token = token.substr(1);
2086  const char *nptr = token.c_str();
2087  char *endptr;
2088  cursor = strtol(nptr, &endptr, 16);
2089  if (!*nptr || *endptr)
2090  log_error("Can not parse address `%s` for %s at %s:%d.\n", nptr, str.c_str(), filename.c_str(), linenum);
2091  continue;
2092  }
2093 
2094  AstNode *value = VERILOG_FRONTEND::const2ast((is_readmemh ? "'h" : "'b") + token);
2095 
2096  block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor, false))), value));
2097  block->children.back()->children[0]->str = memory->str;
2098  block->children.back()->children[0]->id2ast = memory;
2099 
2100  if ((cursor == finish_addr) || (increment > 0 && cursor >= range_max) || (increment < 0 && cursor <= range_min))
2101  break;
2102  cursor += increment;
2103  }
2104 
2105  if ((cursor == finish_addr) || (increment > 0 && cursor >= range_max) || (increment < 0 && cursor <= range_min))
2106  break;
2107  }
2108 
2109  return block;
2110 }
2111 
2112 // annotate the names of all wires and other named objects in a generate block
2113 void AstNode::expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map)
2114 {
2115  if (!index_var.empty() && type == AST_IDENTIFIER && str == index_var) {
2116  current_scope[index_var]->children[0]->cloneInto(this);
2117  return;
2118  }
2119 
2120  if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL) && name_map.count(str) > 0)
2121  str = name_map[str];
2122 
2123  std::map<std::string, std::string> backup_name_map;
2124 
2125  for (size_t i = 0; i < children.size(); i++) {
2126  AstNode *child = children[i];
2127  if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM ||
2128  child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL) {
2129  if (backup_name_map.size() == 0)
2130  backup_name_map = name_map;
2131  std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
2132  size_t pos = child->str.rfind('.');
2133  if (pos == std::string::npos)
2134  pos = child->str[0] == '\\' ? 1 : 0;
2135  else
2136  pos = pos + 1;
2137  new_name = child->str.substr(0, pos) + new_name + child->str.substr(pos);
2138  if (new_name[0] != '$' && new_name[0] != '\\')
2139  new_name = prefix[0] + new_name;
2140  name_map[child->str] = new_name;
2141  if (child->type == AST_FUNCTION)
2142  replace_result_wire_name_in_function(child, child->str, new_name);
2143  else
2144  child->str = new_name;
2145  current_scope[new_name] = child;
2146  }
2147  }
2148 
2149  for (size_t i = 0; i < children.size(); i++) {
2150  AstNode *child = children[i];
2151  if (child->type != AST_FUNCTION && child->type != AST_TASK && child->type != AST_PREFIX)
2152  child->expand_genblock(index_var, prefix, name_map);
2153  }
2154 
2155  if (backup_name_map.size() > 0)
2156  name_map.swap(backup_name_map);
2157 }
2158 
2159 // rename stuff (used when tasks of functions are instanciated)
2160 void AstNode::replace_ids(const std::string &prefix, const std::map<std::string, std::string> &rules)
2161 {
2162  if (type == AST_BLOCK)
2163  {
2164  std::map<std::string, std::string> new_rules = rules;
2165  std::string new_prefix = prefix + str;
2166 
2167  for (auto child : children)
2168  if (child->type == AST_WIRE) {
2169  new_rules[child->str] = new_prefix + child->str;
2170  child->str = new_prefix + child->str;
2171  }
2172 
2173  for (auto child : children)
2174  if (child->type != AST_WIRE)
2175  child->replace_ids(new_prefix, new_rules);
2176  }
2177  else
2178  {
2179  if (type == AST_IDENTIFIER && rules.count(str) > 0)
2180  str = rules.at(str);
2181  for (auto child : children)
2182  child->replace_ids(prefix, rules);
2183  }
2184 }
2185 
2186 // helper function for mem2reg_as_needed_pass1
2187 static void mark_memories_assign_lhs_complex(std::map<AstNode*, std::set<std::string>> &mem2reg_places,
2188  std::map<AstNode*, uint32_t> &mem2reg_candidates, AstNode *that)
2189 {
2190  for (auto &child : that->children)
2191  mark_memories_assign_lhs_complex(mem2reg_places, mem2reg_candidates, child);
2192 
2193  if (that->type == AST_IDENTIFIER && that->id2ast && that->id2ast->type == AST_MEMORY) {
2194  AstNode *mem = that->id2ast;
2195  if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_CMPLX_LHS))
2196  mem2reg_places[mem].insert(stringf("%s:%d", that->filename.c_str(), that->linenum));
2197  mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CMPLX_LHS;
2198  }
2199 }
2200 
2201 // find memories that should be replaced by registers
2202 void AstNode::mem2reg_as_needed_pass1(std::map<AstNode*, std::set<std::string>> &mem2reg_places,
2203  std::map<AstNode*, uint32_t> &mem2reg_candidates, std::map<AstNode*, uint32_t> &proc_flags, uint32_t &flags)
2204 {
2205  uint32_t children_flags = 0;
2206  int ignore_children_counter = 0;
2207 
2208  if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ)
2209  {
2210  // mark all memories that are used in a complex expression on the left side of an assignment
2211  for (auto &lhs_child : children[0]->children)
2212  mark_memories_assign_lhs_complex(mem2reg_places, mem2reg_candidates, lhs_child);
2213 
2214  if (children[0]->type == AST_IDENTIFIER && children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY)
2215  {
2216  AstNode *mem = children[0]->id2ast;
2217 
2218  // activate mem2reg if this is assigned in an async proc
2219  if (flags & AstNode::MEM2REG_FL_ASYNC) {
2220  if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ASYNC))
2221  mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
2222  mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ASYNC;
2223  }
2224 
2225  // remember if this is assigned blocking (=)
2226  if (type == AST_ASSIGN_EQ) {
2227  if (!(proc_flags[mem] & AstNode::MEM2REG_FL_EQ1))
2228  mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
2229  proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1;
2230  }
2231 
2232  // remember where this is
2233  if (flags & MEM2REG_FL_INIT) {
2234  if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT))
2235  mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
2236  mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_INIT;
2237  } else {
2238  if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ELSE))
2239  mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
2240  mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ELSE;
2241  }
2242  }
2243 
2244  ignore_children_counter = 1;
2245  }
2246 
2247  if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY)
2248  {
2249  AstNode *mem = id2ast;
2250 
2251  // flag if used after blocking assignment (in same proc)
2252  if ((proc_flags[mem] & AstNode::MEM2REG_FL_EQ1) && !(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_EQ2)) {
2253  mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
2254  mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_EQ2;
2255  }
2256  }
2257 
2258  // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg'
2259  if (type == AST_MEMORY && (get_bool_attribute("\\mem2reg") || (flags & AstNode::MEM2REG_FL_ALL) || !is_reg))
2260  mem2reg_candidates[this] |= AstNode::MEM2REG_FL_FORCED;
2261 
2262  if (type == AST_MODULE && get_bool_attribute("\\mem2reg"))
2263  children_flags |= AstNode::MEM2REG_FL_ALL;
2264 
2265  std::map<AstNode*, uint32_t> *proc_flags_p = NULL;
2266 
2267  if (type == AST_ALWAYS) {
2268  int count_edge_events = 0;
2269  for (auto child : children)
2270  if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE)
2271  count_edge_events++;
2272  if (count_edge_events != 1)
2273  children_flags |= AstNode::MEM2REG_FL_ASYNC;
2274  proc_flags_p = new std::map<AstNode*, uint32_t>;
2275  }
2276 
2277  if (type == AST_INITIAL) {
2278  children_flags |= AstNode::MEM2REG_FL_INIT;
2279  proc_flags_p = new std::map<AstNode*, uint32_t>;
2280  }
2281 
2282  uint32_t backup_flags = flags;
2283  flags |= children_flags;
2284  log_assert((flags & ~0x000000ff) == 0);
2285 
2286  for (auto child : children)
2287  if (ignore_children_counter > 0)
2288  ignore_children_counter--;
2289  else if (proc_flags_p)
2290  child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags);
2291  else
2292  child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags);
2293 
2294  flags &= ~children_flags | backup_flags;
2295 
2296  if (proc_flags_p) {
2297  for (auto it : *proc_flags_p)
2298  log_assert((it.second & ~0xff000000) == 0);
2299  delete proc_flags_p;
2300  }
2301 }
2302 
2303 bool AstNode::mem2reg_check(std::set<AstNode*> &mem2reg_set)
2304 {
2305  if (type != AST_IDENTIFIER || !id2ast || !mem2reg_set.count(id2ast))
2306  return false;
2307 
2308  if (children.empty() || children[0]->type != AST_RANGE || GetSize(children[0]->children) != 1)
2309  log_error("Invalid array access at %s:%d.\n", filename.c_str(), linenum);
2310 
2311  return true;
2312 }
2313 
2314 // actually replace memories with registers
2315 void AstNode::mem2reg_as_needed_pass2(std::set<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block)
2316 {
2317  if (type == AST_BLOCK)
2318  block = this;
2319 
2320  if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && block != NULL &&
2321  children[0]->mem2reg_check(mem2reg_set) && children[0]->children[0]->children[0]->type != AST_CONSTANT)
2322  {
2323  std::stringstream sstr;
2324  sstr << "$mem2reg_wr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
2325  std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
2326 
2327  int mem_width, mem_size, addr_bits;
2328  children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
2329 
2330  AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
2331  wire_addr->str = id_addr;
2332  wire_addr->is_reg = true;
2333  wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
2334  mod->children.push_back(wire_addr);
2335  while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
2336 
2337  AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
2338  wire_data->str = id_data;
2339  wire_data->is_reg = true;
2340  wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
2341  mod->children.push_back(wire_data);
2342  while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
2343 
2344  log_assert(block != NULL);
2345  size_t assign_idx = 0;
2346  while (assign_idx < block->children.size() && block->children[assign_idx] != this)
2347  assign_idx++;
2348  log_assert(assign_idx < block->children.size());
2349 
2350  AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
2351  assign_addr->children[0]->str = id_addr;
2352  block->children.insert(block->children.begin()+assign_idx+1, assign_addr);
2353 
2354  AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER));
2355  case_node->children[0]->str = id_addr;
2356  for (int i = 0; i < mem_size; i++) {
2357  if (children[0]->children[0]->children[0]->type == AST_CONSTANT && int(children[0]->children[0]->children[0]->integer) != i)
2358  continue;
2359  AstNode *cond_node = new AstNode(AST_COND, AstNode::mkconst_int(i, false, addr_bits), new AstNode(AST_BLOCK));
2360  AstNode *assign_reg = new AstNode(type, new AstNode(AST_IDENTIFIER), new AstNode(AST_IDENTIFIER));
2361  if (children[0]->children.size() == 2)
2362  assign_reg->children[0]->children.push_back(children[0]->children[1]->clone());
2363  assign_reg->children[0]->str = stringf("%s[%d]", children[0]->str.c_str(), i);
2364  assign_reg->children[1]->str = id_data;
2365  cond_node->children[1]->children.push_back(assign_reg);
2366  case_node->children.push_back(cond_node);
2367  }
2368  block->children.insert(block->children.begin()+assign_idx+2, case_node);
2369 
2370  children[0]->delete_children();
2371  children[0]->range_valid = false;
2372  children[0]->id2ast = NULL;
2373  children[0]->str = id_data;
2374  type = AST_ASSIGN_EQ;
2375  }
2376 
2377  if (mem2reg_check(mem2reg_set))
2378  {
2379  AstNode *bit_part_sel = NULL;
2380  if (children.size() == 2)
2381  bit_part_sel = children[1]->clone();
2382 
2383  if (children[0]->children[0]->type == AST_CONSTANT)
2384  {
2385  int id = children[0]->children[0]->integer;
2386  str = stringf("%s[%d]", str.c_str(), id);
2387 
2388  delete_children();
2389  range_valid = false;
2390  id2ast = NULL;
2391  }
2392  else
2393  {
2394  std::stringstream sstr;
2395  sstr << "$mem2reg_rd$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
2396  std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
2397 
2398  int mem_width, mem_size, addr_bits;
2399  id2ast->meminfo(mem_width, mem_size, addr_bits);
2400 
2401  AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
2402  wire_addr->str = id_addr;
2403  wire_addr->is_reg = true;
2404  if (block)
2405  wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
2406  mod->children.push_back(wire_addr);
2407  while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
2408 
2409  AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
2410  wire_data->str = id_data;
2411  wire_data->is_reg = true;
2412  if (block)
2413  wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
2414  mod->children.push_back(wire_data);
2415  while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
2416 
2417  AstNode *assign_addr = new AstNode(block ? AST_ASSIGN_EQ : AST_ASSIGN, new AstNode(AST_IDENTIFIER), children[0]->children[0]->clone());
2418  assign_addr->children[0]->str = id_addr;
2419 
2420  AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER));
2421  case_node->children[0]->str = id_addr;
2422 
2423  for (int i = 0; i < mem_size; i++) {
2424  if (children[0]->children[0]->type == AST_CONSTANT && int(children[0]->children[0]->integer) != i)
2425  continue;
2426  AstNode *cond_node = new AstNode(AST_COND, AstNode::mkconst_int(i, false, addr_bits), new AstNode(AST_BLOCK));
2427  AstNode *assign_reg = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), new AstNode(AST_IDENTIFIER));
2428  assign_reg->children[0]->str = id_data;
2429  assign_reg->children[1]->str = stringf("%s[%d]", str.c_str(), i);
2430  cond_node->children[1]->children.push_back(assign_reg);
2431  case_node->children.push_back(cond_node);
2432  }
2433 
2434  std::vector<RTLIL::State> x_bits;
2435  for (int i = 0; i < mem_width; i++)
2436  x_bits.push_back(RTLIL::State::Sx);
2437 
2438  AstNode *cond_node = new AstNode(AST_COND, new AstNode(AST_DEFAULT), new AstNode(AST_BLOCK));
2439  AstNode *assign_reg = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), AstNode::mkconst_bits(x_bits, false));
2440  assign_reg->children[0]->str = id_data;
2441  cond_node->children[1]->children.push_back(assign_reg);
2442  case_node->children.push_back(cond_node);
2443 
2444  if (block)
2445  {
2446  size_t assign_idx = 0;
2447  while (assign_idx < block->children.size() && !block->children[assign_idx]->contains(this))
2448  assign_idx++;
2449  log_assert(assign_idx < block->children.size());
2450  block->children.insert(block->children.begin()+assign_idx, case_node);
2451  block->children.insert(block->children.begin()+assign_idx, assign_addr);
2452  }
2453  else
2454  {
2455  AstNode *proc = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK));
2456  proc->children[0]->children.push_back(case_node);
2457  mod->children.push_back(proc);
2458  mod->children.push_back(assign_addr);
2459  }
2460 
2461  delete_children();
2462  range_valid = false;
2463  id2ast = NULL;
2464  str = id_data;
2465  }
2466 
2467  if (bit_part_sel)
2468  children.push_back(bit_part_sel);
2469  }
2470 
2471  log_assert(id2ast == NULL || mem2reg_set.count(id2ast) == 0);
2472 
2473  auto children_list = children;
2474  for (size_t i = 0; i < children_list.size(); i++)
2475  children_list[i]->mem2reg_as_needed_pass2(mem2reg_set, mod, block);
2476 }
2477 
2478 // calulate memory dimensions
2479 void AstNode::meminfo(int &mem_width, int &mem_size, int &addr_bits)
2480 {
2481  log_assert(type == AST_MEMORY);
2482 
2483  mem_width = children[0]->range_left - children[0]->range_right + 1;
2484  mem_size = children[1]->range_left - children[1]->range_right;
2485 
2486  if (mem_size < 0)
2487  mem_size *= -1;
2488  mem_size += std::min(children[1]->range_left, children[1]->range_right) + 1;
2489 
2490  addr_bits = 1;
2491  while ((1 << addr_bits) < mem_size)
2492  addr_bits++;
2493 }
2494 
2495 bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
2496 {
2497  if (type == AST_FOR)
2498  recommend_const_eval = true;
2499  if (type == AST_WHILE || type == AST_REPEAT)
2500  return true;
2501  if (type == AST_FCALL && current_scope.count(str))
2502  if (current_scope[str]->has_const_only_constructs(recommend_const_eval))
2503  return true;
2504  for (auto child : children)
2505  if (child->AstNode::has_const_only_constructs(recommend_const_eval))
2506  return true;
2507  return false;
2508 }
2509 
2510 // helper function for AstNode::eval_const_function()
2511 void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall)
2512 {
2513  if (type == AST_IDENTIFIER && variables.count(str)) {
2514  int offset = variables.at(str).offset, width = variables.at(str).val.bits.size();
2515  if (!children.empty()) {
2516  if (children.size() != 1 || children.at(0)->type != AST_RANGE)
2517  log_error("Memory access in constant function is not supported in %s:%d (called from %s:%d).\n",
2518  filename.c_str(), linenum, fcall->filename.c_str(), fcall->linenum);
2519  children.at(0)->replace_variables(variables, fcall);
2520  while (simplify(true, false, false, 1, -1, false, true)) { }
2521  if (!children.at(0)->range_valid)
2522  log_error("Non-constant range in %s:%d (called from %s:%d).\n",
2523  filename.c_str(), linenum, fcall->filename.c_str(), fcall->linenum);
2524  offset = std::min(children.at(0)->range_left, children.at(0)->range_right);
2525  width = std::min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);
2526  }
2527  offset -= variables.at(str).offset;
2528  std::vector<RTLIL::State> &var_bits = variables.at(str).val.bits;
2529  std::vector<RTLIL::State> new_bits(var_bits.begin() + offset, var_bits.begin() + offset + width);
2530  AstNode *newNode = mkconst_bits(new_bits, variables.at(str).is_signed);
2531  newNode->cloneInto(this);
2532  delete newNode;
2533  return;
2534  }
2535 
2536  for (auto &child : children)
2537  child->replace_variables(variables, fcall);
2538 }
2539 
2540 // evaluate functions with all-const arguments
2542 {
2543  std::map<std::string, AstNode*> backup_scope;
2544  std::map<std::string, AstNode::varinfo_t> variables;
2545  bool delete_temp_block = false;
2546  AstNode *block = NULL;
2547 
2548  size_t argidx = 0;
2549  for (auto child : children)
2550  {
2551  if (child->type == AST_BLOCK)
2552  {
2553  log_assert(block == NULL);
2554  block = child;
2555  continue;
2556  }
2557 
2558  if (child->type == AST_WIRE)
2559  {
2560  while (child->simplify(true, false, false, 1, -1, false, true)) { }
2561  if (!child->range_valid)
2562  log_error("Can't determine size of variable %s in %s:%d (called from %s:%d).\n",
2563  child->str.c_str(), child->filename.c_str(), child->linenum, fcall->filename.c_str(), fcall->linenum);
2564  variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1);
2565  variables[child->str].offset = std::min(child->range_left, child->range_right);
2566  variables[child->str].is_signed = child->is_signed;
2567  if (child->is_input && argidx < fcall->children.size())
2568  variables[child->str].val = fcall->children.at(argidx++)->bitsAsConst(variables[child->str].val.bits.size());
2569  backup_scope[child->str] = current_scope[child->str];
2570  current_scope[child->str] = child;
2571  continue;
2572  }
2573 
2574  log_assert(block == NULL);
2575  delete_temp_block = true;
2576  block = new AstNode(AST_BLOCK);
2577  block->children.push_back(child->clone());
2578  }
2579 
2580  log_assert(block != NULL);
2581  log_assert(variables.count(str) != 0);
2582 
2583  while (!block->children.empty())
2584  {
2585  AstNode *stmt = block->children.front();
2586 
2587 #if 0
2588  log("-----------------------------------\n");
2589  for (auto &it : variables)
2590  log("%20s %40s\n", it.first.c_str(), log_signal(it.second.val));
2591  stmt->dumpAst(NULL, "stmt> ");
2592 #endif
2593 
2594  if (stmt->type == AST_ASSIGN_EQ)
2595  {
2596  stmt->children.at(1)->replace_variables(variables, fcall);
2597  while (stmt->simplify(true, false, false, 1, -1, false, true)) { }
2598 
2599  if (stmt->type != AST_ASSIGN_EQ)
2600  continue;
2601 
2602  if (stmt->children.at(1)->type != AST_CONSTANT)
2603  log_error("Non-constant expression in constant function at %s:%d (called from %s:%d). X\n",
2604  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2605 
2606  if (stmt->children.at(0)->type != AST_IDENTIFIER)
2607  log_error("Unsupported composite left hand side in constant function at %s:%d (called from %s:%d).\n",
2608  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2609 
2610  if (!variables.count(stmt->children.at(0)->str))
2611  log_error("Assignment to non-local variable in constant function at %s:%d (called from %s:%d).\n",
2612  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2613 
2614  if (stmt->children.at(0)->children.empty()) {
2615  variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size());
2616  } else {
2617  AstNode *range = stmt->children.at(0)->children.at(0);
2618  if (!range->range_valid)
2619  log_error("Non-constant range in %s:%d (called from %s:%d).\n",
2620  range->filename.c_str(), range->linenum, fcall->filename.c_str(), fcall->linenum);
2621  int offset = std::min(range->range_left, range->range_right);
2622  int width = std::abs(range->range_left - range->range_right) + 1;
2623  varinfo_t &v = variables[stmt->children.at(0)->str];
2624  RTLIL::Const r = stmt->children.at(1)->bitsAsConst(v.val.bits.size());
2625  for (int i = 0; i < width; i++)
2626  v.val.bits.at(i+offset-v.offset) = r.bits.at(i);
2627  }
2628 
2629  delete block->children.front();
2630  block->children.erase(block->children.begin());
2631  continue;
2632  }
2633 
2634  if (stmt->type == AST_FOR)
2635  {
2636  block->children.insert(block->children.begin(), stmt->children.at(0));
2637  stmt->children.at(3)->children.push_back(stmt->children.at(2));
2638  stmt->children.erase(stmt->children.begin() + 2);
2639  stmt->children.erase(stmt->children.begin());
2640  stmt->type = AST_WHILE;
2641  continue;
2642  }
2643 
2644  if (stmt->type == AST_WHILE)
2645  {
2646  AstNode *cond = stmt->children.at(0)->clone();
2647  cond->replace_variables(variables, fcall);
2648  while (cond->simplify(true, false, false, 1, -1, false, true)) { }
2649 
2650  if (cond->type != AST_CONSTANT)
2651  log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
2652  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2653 
2654  if (cond->asBool()) {
2655  block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
2656  } else {
2657  delete block->children.front();
2658  block->children.erase(block->children.begin());
2659  }
2660 
2661  delete cond;
2662  continue;
2663  }
2664 
2665  if (stmt->type == AST_REPEAT)
2666  {
2667  AstNode *num = stmt->children.at(0)->clone();
2668  num->replace_variables(variables, fcall);
2669  while (num->simplify(true, false, false, 1, -1, false, true)) { }
2670 
2671  if (num->type != AST_CONSTANT)
2672  log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
2673  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2674 
2675  block->children.erase(block->children.begin());
2676  for (int i = 0; i < num->bitsAsConst().as_int(); i++)
2677  block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
2678 
2679  delete stmt;
2680  delete num;
2681  continue;
2682  }
2683 
2684  if (stmt->type == AST_CASE)
2685  {
2686  AstNode *expr = stmt->children.at(0)->clone();
2687  expr->replace_variables(variables, fcall);
2688  while (expr->simplify(true, false, false, 1, -1, false, true)) { }
2689 
2690  AstNode *sel_case = NULL;
2691  for (size_t i = 1; i < stmt->children.size(); i++)
2692  {
2693  bool found_match = false;
2694  log_assert(stmt->children.at(i)->type == AST_COND);
2695 
2696  if (stmt->children.at(i)->children.front()->type == AST_DEFAULT) {
2697  sel_case = stmt->children.at(i)->children.back();
2698  continue;
2699  }
2700 
2701  for (size_t j = 0; j+1 < stmt->children.at(i)->children.size() && !found_match; j++)
2702  {
2703  AstNode *cond = stmt->children.at(i)->children.at(j)->clone();
2704  cond->replace_variables(variables, fcall);
2705 
2706  cond = new AstNode(AST_EQ, expr->clone(), cond);
2707  while (cond->simplify(true, false, false, 1, -1, false, true)) { }
2708 
2709  if (cond->type != AST_CONSTANT)
2710  log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
2711  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2712 
2713  found_match = cond->asBool();
2714  delete cond;
2715  }
2716 
2717  if (found_match) {
2718  sel_case = stmt->children.at(i)->children.back();
2719  break;
2720  }
2721  }
2722 
2723  block->children.erase(block->children.begin());
2724  if (sel_case)
2725  block->children.insert(block->children.begin(), sel_case->clone());
2726  delete stmt;
2727  delete expr;
2728  continue;
2729  }
2730 
2731  if (stmt->type == AST_BLOCK)
2732  {
2733  block->children.erase(block->children.begin());
2734  block->children.insert(block->children.begin(), stmt->children.begin(), stmt->children.end());
2735  stmt->children.clear();
2736  delete stmt;
2737  continue;
2738  }
2739 
2740  log_error("Unsupported language construct in constant function at %s:%d (called from %s:%d).\n",
2741  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2742  log_abort();
2743  }
2744 
2745  if (delete_temp_block)
2746  delete block;
2747 
2748  for (auto &it : backup_scope)
2749  if (it.second == NULL)
2750  current_scope.erase(it.first);
2751  else
2752  current_scope[it.first] = it.second;
2753 
2754  return AstNode::mkconst_bits(variables.at(str).val.bits, variables.at(str).is_signed);
2755 }
2756 
2758 
std::map< std::string, AstNode * > current_scope
Definition: ast.cc:58
static std::string next_token(bool pass_newline=false)
Definition: preproc.cc:96
RTLIL::Const bitsAsConst(int width, bool is_signed)
Definition: ast.cc:741
RTLIL::Const const_logic_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:256
bool range_valid
Definition: ast.h:158
RTLIL::Const const_xor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:175
static AstNode * mkconst_int(uint32_t v, bool is_signed, int width=32)
Definition: ast.cc:672
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
RTLIL::Const const_pow(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:511
AstNode * current_top_block
Definition: ast.cc:61
AstNode * dpi_call(const std::string &rtype, const std::string &fname, const std::vector< std::string > &argtypes, const std::vector< AstNode * > &args)
Definition: dpicall.cc:140
void log_warning(const char *format,...)
Definition: log.cc:196
RTLIL::Const val
Definition: ast.h:217
RTLIL::Const const_ne(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:403
static AstNode * mkconst_bits(const std::vector< RTLIL::State > &v, bool is_signed)
Definition: ast.cc:688
AstNode * current_block
Definition: ast.cc:61
RTLIL::Const const_eq(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:379
#define YOSYS_NAMESPACE_END
Definition: yosys.h:100
void dumpAst(FILE *f, std::string indent)
Definition: ast.cc:250
RTLIL::Const as_const() const
Definition: rtlil.cc:2857
static std::string unescape_id(std::string str)
Definition: rtlil.h:257
void mem2reg_as_needed_pass1(std::map< AstNode *, std::set< std::string >> &mem2reg_places, std::map< AstNode *, uint32_t > &mem2reg_flags, std::map< AstNode *, uint32_t > &proc_flags, uint32_t &status_flags)
Definition: simplify.cc:2202
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
Definition: log.cc:269
static std::string idx(std::string str)
Definition: test_autotb.cc:57
RTLIL::Const const_sub(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:471
RTLIL::Const const_logic_not(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:230
void(* set_line_num)(int)
Definition: ast.cc:50
std::map< RTLIL::IdString, AstNode * > attributes
Definition: ast.h:152
void log_error(const char *format,...)
Definition: log.cc:204
void extend_u0(int width, bool is_signed=false)
Definition: rtlil.cc:2612
AstNode * id2ast
Definition: ast.h:167
bool mem2reg_check(std::set< AstNode * > &mem2reg_set)
Definition: simplify.cc:2303
#define log_abort()
Definition: log.h:84
RTLIL::Const const_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:170
bool get_bool_attribute(RTLIL::IdString id)
Definition: ast.cc:166
RTLIL::Const const_ge(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:442
RTLIL::Const const_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:165
RTLIL::Const const_mul(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:478
static void replace_result_wire_name_in_function(AstNode *node, std::string &from, std::string &to)
Definition: simplify.cc:2027
static std::string escape_id(std::string str)
Definition: rtlil.h:251
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN bool did_something
Definition: opt_const.cc:32
RTLIL::Const const_reduce_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:198
void cloneInto(AstNode *other)
Definition: ast.cc:220
static void mark_memories_assign_lhs_complex(std::map< AstNode *, std::set< std::string >> &mem2reg_places, std::map< AstNode *, uint32_t > &mem2reg_candidates, AstNode *that)
Definition: simplify.cc:2187
RTLIL::Const const_reduce_xor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:208
double asReal(bool is_signed)
Definition: ast.cc:822
RTLIL::Const const_sshl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:310
int range_right
Definition: ast.h:159
RTLIL::Const const_reduce_xnor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:213
AstNodeType
Definition: ast.h:42
bool is_reg
Definition: ast.h:158
RTLIL::Const const_xnor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:180
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
std::string decode_string() const
Definition: rtlil.cc:131
#define log_assert(_assert_expr_)
Definition: log.h:85
RTLIL::Const const_shr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:303
double realvalue
Definition: ast.h:161
RTLIL::Const const_mod(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:498
RTLIL::Const const_shl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:296
void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real=NULL)
Definition: genrtlil.cc:746
AstNode * current_block_child
Definition: ast.cc:61
RTLIL::Const const_le(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:368
RTLIL::Const const_eqx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:413
list variables
Definition: fsm/generate.py:47
AstNodeType type
Definition: ast.h:146
AstNode * eval_const_function(AstNode *fcall)
Definition: simplify.cc:2541
RTLIL::Const const_sshr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:317
uint32_t integer
Definition: ast.h:160
int as_int(bool is_signed=false) const
Definition: rtlil.cc:104
int range_left
Definition: ast.h:159
void meminfo(int &mem_width, int &mem_size, int &addr_bits)
Definition: simplify.cc:2479
void expand_genblock(std::string index_var, std::string prefix, std::map< std::string, std::string > &name_map)
Definition: simplify.cc:2113
std::string current_filename
Definition: ast.cc:49
RTLIL::Const const_logic_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:241
AstNode * clone()
Definition: ast.cc:208
#define NULL
RTLIL::Const const_reduce_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:203
#define YOSYS_NAMESPACE_BEGIN
Definition: yosys.h:99
bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
Definition: simplify.cc:50
RTLIL::Const const_nex(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:432
RTLIL::Const const_div(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:485
std::string filename
Definition: ast.h:175
RTLIL::Const const_lt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:357
AstNode * current_ast_mod
Definition: ast.cc:57
void log(const char *format,...)
Definition: log.cc:180
AstNode * readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr)
Definition: simplify.cc:2036
std::vector< RTLIL::State > bits
Definition: rtlil.h:438
bool is_signed
Definition: ast.h:158
RTLIL::Const const_neg(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:570
RTLIL::Const const_add(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:464
std::string str
Definition: ast.h:156
std::vector< AstNode * > children
Definition: ast.h:149
void replace_ids(const std::string &prefix, const std::map< std::string, std::string > &rules)
Definition: simplify.cc:2160
AST::AstNode * const2ast(std::string code, char case_type=0, bool warn_z=false)
Definition: const2ast.cc:135
bool flag_mem2reg
Definition: ast.cc:56
std::string id(RTLIL::IdString internal_id, bool may_rename=true)
bool is_string
Definition: ast.h:158
int linenum
Definition: ast.h:176
uint64_t asInt(bool is_signed)
Definition: ast.cc:802
RTLIL::Const const_reduce_bool(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:225
int isConst()
Definition: ast.cc:793
void replace_variables(std::map< std::string, varinfo_t > &variables, AstNode *fcall)
Definition: simplify.cc:2511
bool flag_nomem2reg
Definition: ast.cc:56
void delete_children()
Definition: ast.cc:231
RTLIL::Const const_pos(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:562
RTLIL::Const const_gt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:453
void mem2reg_as_needed_pass2(std::set< AstNode * > &mem2reg_set, AstNode *mod, AstNode *block)
Definition: simplify.cc:2315
const char * log_id(RTLIL::IdString str)
Definition: log.cc:283
bool is_output
Definition: ast.h:158
YOSYS_NAMESPACE_BEGIN int autoidx
Definition: yosys.cc:51
RTLIL::Const const_not(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:125
int port_id
Definition: ast.h:159
bool asBool()
Definition: ast.cc:784
bool has_const_only_constructs(bool &recommend_const_eval)
Definition: simplify.cc:2495
bool is_input
Definition: ast.h:158