2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
20 * This is the AST frontend library.
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.
29 #include "kernel/log.h"
30 #include "libs/sha1/sha1.h"
31 #include "frontends/verilog/verilog_frontend.h"
42 using namespace AST_INTERNAL
;
44 // Process a format string and arguments for $display, $write, $sprintf, etc
46 std::string
AstNode::process_format_str(const std::string
&sformat
, int next_arg
, int stage
, int width_hint
, bool sign_hint
) {
47 // Other arguments are placeholders. Process the string as we go through it
49 for (size_t i
= 0; i
< sformat
.length(); i
++)
52 if (sformat
[i
] == '%')
54 // If there's no next character, that's a problem
55 if (i
+1 >= sformat
.length())
56 log_file_error(filename
, location
.first_line
, "System task `%s' called with `%%' at end of string.\n", str
.c_str());
58 char cformat
= sformat
[++i
];
60 // %% is special, does not need a matching argument
68 bool got_zlen
= false;
71 while ('0' <= cformat
&& cformat
<= '9')
73 if (!got_len
&& cformat
== '0')
77 len_value
= 10*len_value
+ (cformat
- '0');
79 cformat
= sformat
[++i
];
82 // Simplify the argument
83 AstNode
*node_arg
= nullptr;
85 // Everything from here on depends on the format specifier
93 goto unsupported_format
;
97 if (next_arg
>= GetSize(children
))
98 log_file_error(filename
, location
.first_line
, "Missing argument for %%%c format specifier in system task `%s'.\n",
99 cformat
, str
.c_str());
101 node_arg
= children
[next_arg
++];
102 while (node_arg
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
103 if (node_arg
->type
!= AST_CONSTANT
)
104 log_file_error(filename
, location
.first_line
, "Failed to evaluate system task `%s' with non-constant argument.\n", str
.c_str());
110 goto unsupported_format
;
115 log_file_error(filename
, location
.first_line
, "System task `%s' called with invalid/unsupported format specifier.\n", str
.c_str());
123 sout
+= node_arg
->bitsAsConst().decode_string();
128 sout
+= stringf("%d", node_arg
->bitsAsConst().as_int());
134 Const val
= node_arg
->bitsAsConst();
136 while (GetSize(val
) % 4 != 0)
137 val
.bits
.push_back(State::S0
);
139 int len
= GetSize(val
) / 4;
140 for (int i
= len
; i
< len_value
; i
++)
141 sout
+= got_zlen
? '0' : ' ';
143 for (int i
= len
-1; i
>= 0; i
--) {
144 Const digit
= val
.extract(4*i
, 4);
145 if (digit
.is_fully_def())
146 sout
+= stringf(cformat
== 'x' ? "%x" : "%X", digit
.as_int());
148 sout
+= cformat
== 'x' ? "x" : "X";
155 sout
+= log_id(current_module
->name
);
163 // not a format specifier
171 void AstNode::annotateTypedEnums(AstNode
*template_node
)
174 if (template_node
->attributes
.count(ID::enum_type
)) {
175 //get reference to enum node:
176 std::string enum_type
= template_node
->attributes
[ID::enum_type
]->str
.c_str();
177 // log("enum_type=%s (count=%lu)\n", enum_type.c_str(), current_scope.count(enum_type));
178 // log("current scope:\n");
179 // for (auto &it : current_scope)
180 // log(" %s\n", it.first.c_str());
181 log_assert(current_scope
.count(enum_type
) == 1);
182 AstNode
*enum_node
= current_scope
.at(enum_type
);
183 log_assert(enum_node
->type
== AST_ENUM
);
184 //get width from 1st enum item:
185 log_assert(enum_node
->children
.size() >= 1);
186 AstNode
*enum_item0
= enum_node
->children
[0];
187 log_assert(enum_item0
->type
== AST_ENUM_ITEM
);
189 if (!enum_item0
->range_valid
)
191 else if (enum_item0
->range_swapped
)
192 width
= enum_item0
->range_right
- enum_item0
->range_left
+ 1;
194 width
= enum_item0
->range_left
- enum_item0
->range_right
+ 1;
195 log_assert(width
> 0);
196 //add declared enum items:
197 for (auto enum_item
: enum_node
->children
){
198 log_assert(enum_item
->type
== AST_ENUM_ITEM
);
201 if (enum_item
->children
.size() == 1){
203 } else if (enum_item
->children
.size() == 2){
204 log_assert(enum_item
->children
[1]->type
== AST_RANGE
);
205 is_signed
= enum_item
->children
[1]->is_signed
;
207 log_error("enum_item children size==%lu, expected 1 or 2 for %s (%s)\n",
208 enum_item
->children
.size(),
209 enum_item
->str
.c_str(), enum_node
->str
.c_str()
212 //start building attribute string
213 std::string enum_item_str
= "\\enum_value_";
214 //get enum item value
215 if(enum_item
->children
[0]->type
!= AST_CONSTANT
){
216 log_error("expected const, got %s for %s (%s)\n",
217 type2str(enum_item
->children
[0]->type
).c_str(),
218 enum_item
->str
.c_str(), enum_node
->str
.c_str()
221 RTLIL::Const val
= enum_item
->children
[0]->bitsAsConst(width
, is_signed
);
222 enum_item_str
.append(val
.as_string());
223 //set attribute for available val to enum item name mappings
224 attributes
[enum_item_str
.c_str()] = mkconst_str(enum_item
->str
);
229 static bool name_has_dot(const std::string
&name
, std::string
&struct_name
)
231 // check if plausible struct member name \sss.mmm
232 std::string::size_type pos
;
233 if (name
.substr(0, 1) == "\\" && (pos
= name
.find('.', 0)) != std::string::npos
) {
234 struct_name
= name
.substr(0, pos
);
240 static AstNode
*make_range(int left
, int right
, bool is_signed
= false)
242 // generate a pre-validated range node for a fixed signal range.
243 auto range
= new AstNode(AST_RANGE
);
244 range
->range_left
= left
;
245 range
->range_right
= right
;
246 range
->range_valid
= true;
247 range
->children
.push_back(AstNode::mkconst_int(left
, true));
248 range
->children
.push_back(AstNode::mkconst_int(right
, true));
249 range
->is_signed
= is_signed
;
253 static int range_width(AstNode
*node
, AstNode
*rnode
)
255 log_assert(rnode
->type
==AST_RANGE
);
256 if (!rnode
->range_valid
) {
257 log_file_error(node
->filename
, node
->location
.first_line
, "Size must be constant in packed struct/union member %s\n", node
->str
.c_str());
260 // note: range swapping has already been checked for
261 return rnode
->range_left
- rnode
->range_right
+ 1;
264 [[noreturn
]] static void struct_array_packing_error(AstNode
*node
)
266 log_file_error(node
->filename
, node
->location
.first_line
, "Unpacked array in packed struct/union member %s\n", node
->str
.c_str());
269 static void save_struct_array_width(AstNode
*node
, int width
)
271 // stash the stride for the array
272 node
->multirange_dimensions
.push_back(width
);
276 static int get_struct_array_width(AstNode
*node
)
278 // the stride for the array, 1 if not an array
279 return (node
->multirange_dimensions
.empty() ? 1 : node
->multirange_dimensions
.back());
283 static int size_packed_struct(AstNode
*snode
, int base_offset
)
285 // Struct members will be laid out in the structure contiguously from left to right.
286 // Union members all have zero offset from the start of the union.
287 // Determine total packed size and assign offsets. Store these in the member node.
288 bool is_union
= (snode
->type
== AST_UNION
);
290 int packed_width
= -1;
291 // examine members from last to first
292 for (auto it
= snode
->children
.rbegin(); it
!= snode
->children
.rend(); ++it
) {
295 if (node
->type
== AST_STRUCT
|| node
->type
== AST_UNION
) {
296 // embedded struct or union
297 width
= size_packed_struct(node
, base_offset
+ offset
);
300 log_assert(node
->type
== AST_STRUCT_ITEM
);
301 if (node
->children
.size() > 0 && node
->children
[0]->type
== AST_RANGE
) {
302 // member width e.g. bit [7:0] a
303 width
= range_width(node
, node
->children
[0]);
304 if (node
->children
.size() == 2) {
305 if (node
->children
[1]->type
== AST_RANGE
) {
306 // unpacked array e.g. bit [63:0] a [0:3]
307 auto rnode
= node
->children
[1];
308 int array_count
= range_width(node
, rnode
);
309 if (array_count
== 1) {
310 // C-type array size e.g. bit [63:0] a [4]
311 array_count
= rnode
->range_left
;
313 save_struct_array_width(node
, width
);
314 width
*= array_count
;
317 // array element must be single bit for a packed array
318 struct_array_packing_error(node
);
321 // range nodes are now redundant
322 node
->children
.clear();
324 else if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_MULTIRANGE
) {
325 // packed 2D array, e.g. bit [3:0][63:0] a
326 auto rnode
= node
->children
[0];
327 if (rnode
->children
.size() != 2) {
328 // packed arrays can only be 2D
329 struct_array_packing_error(node
);
331 int array_count
= range_width(node
, rnode
->children
[0]);
332 width
= range_width(node
, rnode
->children
[1]);
333 save_struct_array_width(node
, width
);
334 width
*= array_count
;
335 // range nodes are now redundant
336 node
->children
.clear();
338 else if (node
->range_left
< 0) {
339 // 1 bit signal: bit, logic or reg
343 // already resolved and compacted
344 width
= node
->range_left
- node
->range_right
+ 1;
347 node
->range_right
= base_offset
;
348 node
->range_left
= base_offset
+ width
- 1;
351 node
->range_right
= base_offset
+ offset
;
352 node
->range_left
= base_offset
+ offset
+ width
- 1;
354 node
->range_valid
= true;
357 // check that all members have the same size
358 if (packed_width
== -1) {
360 packed_width
= width
;
363 if (packed_width
!= width
) {
365 log_file_error(node
->filename
, node
->location
.first_line
, "member %s of a packed union has %d bits, expecting %d\n", node
->str
.c_str(), width
, packed_width
);
373 return (is_union
? packed_width
: offset
);
376 [[noreturn
]] static void struct_op_error(AstNode
*node
)
378 log_file_error(node
->filename
, node
->location
.first_line
, "Unsupported operation for struct/union member %s\n", node
->str
.c_str()+1);
381 static AstNode
*node_int(int ival
)
383 // maybe mkconst_int should have default values for the common integer case
384 return AstNode::mkconst_int(ival
, true, 32);
387 static AstNode
*offset_indexed_range(int offset_right
, int stride
, AstNode
*left_expr
, AstNode
*right_expr
)
389 // adjust the range expressions to add an offset into the struct
390 // and maybe index using an array stride
391 auto left
= left_expr
->clone();
392 auto right
= right_expr
->clone();
394 // just add the offset
395 left
= new AstNode(AST_ADD
, node_int(offset_right
), left
);
396 right
= new AstNode(AST_ADD
, node_int(offset_right
), right
);
399 // newleft = offset_right - 1 + (left + 1) * stride
400 left
= new AstNode(AST_ADD
, new AstNode(AST_SUB
, node_int(offset_right
), node_int(1)),
401 new AstNode(AST_MUL
, node_int(stride
), new AstNode(AST_ADD
, left
, node_int(1))));
402 // newright = offset_right + right * stride
403 right
= new AstNode(AST_ADD
, node_int(offset_right
), new AstNode(AST_MUL
, right
, node_int(stride
)));
405 return new AstNode(AST_RANGE
, left
, right
);
408 static AstNode
*make_struct_member_range(AstNode
*node
, AstNode
*member_node
)
410 // Work out the range in the packed array that corresponds to a struct member
411 // taking into account any range operations applicable to the current node
412 // such as array indexing or slicing
413 int range_left
= member_node
->range_left
;
414 int range_right
= member_node
->range_right
;
415 if (node
->children
.empty()) {
416 // no range operations apply, return the whole width
418 else if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
419 auto rnode
= node
->children
[0];
420 int stride
= get_struct_array_width(member_node
);
421 if (rnode
->children
.size() == 1) {
423 return offset_indexed_range(range_right
, stride
, rnode
->children
[0], rnode
->children
[0]);
425 else if (rnode
->children
.size() == 2) {
426 // slice e.g. s.a[i:j]
427 return offset_indexed_range(range_right
, stride
, rnode
->children
[0], rnode
->children
[1]);
430 struct_op_error(node
);
434 // TODO multirange, i.e. bit slice after array index s.a[i][p:q]
435 struct_op_error(node
);
437 return make_range(range_left
, range_right
);
440 static void add_members_to_scope(AstNode
*snode
, std::string name
)
442 // add all the members in a struct or union to local scope
443 // in case later referenced in assignments
444 log_assert(snode
->type
==AST_STRUCT
|| snode
->type
==AST_UNION
);
445 for (auto *node
: snode
->children
) {
446 if (node
->type
!= AST_STRUCT_ITEM
) {
447 // embedded struct or union
448 add_members_to_scope(node
, name
+ "." + node
->str
);
451 auto member_name
= name
+ "." + node
->str
;
452 current_scope
[member_name
] = node
;
457 static int get_max_offset(AstNode
*node
)
459 // get the width from the MS member in the struct
460 // as members are laid out from left to right in the packed wire
461 log_assert(node
->type
==AST_STRUCT
|| node
->type
==AST_UNION
);
462 while (node
->type
!= AST_STRUCT_ITEM
) {
463 node
= node
->children
[0];
465 return node
->range_left
;
468 static AstNode
*make_packed_struct(AstNode
*template_node
, std::string
&name
)
470 // create a wire for the packed struct
471 auto wnode
= new AstNode(AST_WIRE
);
473 wnode
->is_logic
= true;
474 wnode
->range_valid
= true;
475 wnode
->is_signed
= template_node
->is_signed
;
476 int offset
= get_max_offset(template_node
);
477 auto range
= make_range(offset
, 0);
478 wnode
->children
.push_back(range
);
479 // make sure this node is the one in scope for this name
480 current_scope
[name
] = wnode
;
481 // add all the struct members to scope under the wire's name
482 add_members_to_scope(template_node
, name
);
486 // convert the AST into a simpler AST that has all parameters substituted by their
487 // values, unrolled for-loops, expanded generate blocks, etc. when this function
488 // is done with an AST it can be converted into RTLIL using genRTLIL().
490 // this function also does all name resolving and sets the id2ast member of all
491 // nodes that link to a different node using names and lexical scoping.
492 bool AstNode::simplify(bool const_fold
, bool at_zero
, bool in_lvalue
, int stage
, int width_hint
, bool sign_hint
, bool in_param
)
494 static int recursion_counter
= 0;
495 static bool deep_recursion_warning
= false;
497 if (recursion_counter
++ == 1000 && deep_recursion_warning
) {
498 log_warning("Deep recursion in AST simplifier.\nDoes this design contain insanely long expressions?\n");
499 deep_recursion_warning
= false;
502 AstNode
*newNode
= NULL
;
503 bool did_something
= false;
506 log("-------------\n");
507 log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage
, recursion_counter
, filename
.c_str(), location
.first_line
, type2str(type
).c_str(), this);
508 log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
509 int(const_fold
), int(at_zero
), int(in_lvalue
), int(stage
), int(width_hint
), int(sign_hint
), int(in_param
));
510 // dumpAst(NULL, "> ");
515 log_assert(type
== AST_MODULE
|| type
== AST_INTERFACE
);
517 deep_recursion_warning
= true;
518 while (simplify(const_fold
, at_zero
, in_lvalue
, 1, width_hint
, sign_hint
, in_param
)) { }
520 if (!flag_nomem2reg
&& !get_bool_attribute(ID::nomem2reg
))
522 dict
<AstNode
*, pool
<std::string
>> mem2reg_places
;
523 dict
<AstNode
*, uint32_t> mem2reg_candidates
, dummy_proc_flags
;
524 uint32_t flags
= flag_mem2reg
? AstNode::MEM2REG_FL_ALL
: 0;
525 mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, dummy_proc_flags
, flags
);
527 pool
<AstNode
*> mem2reg_set
;
528 for (auto &it
: mem2reg_candidates
)
530 AstNode
*mem
= it
.first
;
531 uint32_t memflags
= it
.second
;
532 bool this_nomeminit
= flag_nomeminit
;
533 log_assert((memflags
& ~0x00ffff00) == 0);
535 if (mem
->get_bool_attribute(ID::nomem2reg
))
538 if (mem
->get_bool_attribute(ID::nomeminit
) || get_bool_attribute(ID::nomeminit
))
539 this_nomeminit
= true;
541 if (memflags
& AstNode::MEM2REG_FL_FORCED
)
542 goto silent_activate
;
544 if (memflags
& AstNode::MEM2REG_FL_EQ2
)
545 goto verbose_activate
;
547 if (memflags
& AstNode::MEM2REG_FL_SET_ASYNC
)
548 goto verbose_activate
;
550 if ((memflags
& AstNode::MEM2REG_FL_SET_INIT
) && (memflags
& AstNode::MEM2REG_FL_SET_ELSE
) && this_nomeminit
)
551 goto verbose_activate
;
553 if (memflags
& AstNode::MEM2REG_FL_CMPLX_LHS
)
554 goto verbose_activate
;
556 if ((memflags
& AstNode::MEM2REG_FL_CONST_LHS
) && !(memflags
& AstNode::MEM2REG_FL_VAR_LHS
))
557 goto verbose_activate
;
559 // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
563 if (mem2reg_set
.count(mem
) == 0) {
564 std::string message
= stringf("Replacing memory %s with list of registers.", mem
->str
.c_str());
565 bool first_element
= true;
566 for (auto &place
: mem2reg_places
[it
.first
]) {
567 message
+= stringf("%s%s", first_element
? " See " : ", ", place
.c_str());
568 first_element
= false;
570 log_warning("%s\n", message
.c_str());
574 // log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
575 mem2reg_set
.insert(mem
);
578 for (auto node
: mem2reg_set
)
580 int mem_width
, mem_size
, addr_bits
;
581 node
->meminfo(mem_width
, mem_size
, addr_bits
);
583 int data_range_left
= node
->children
[0]->range_left
;
584 int data_range_right
= node
->children
[0]->range_right
;
586 if (node
->children
[0]->range_swapped
)
587 std::swap(data_range_left
, data_range_right
);
589 for (int i
= 0; i
< mem_size
; i
++) {
590 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
591 mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
592 reg
->str
= stringf("%s[%d]", node
->str
.c_str(), i
);
594 reg
->is_signed
= node
->is_signed
;
595 for (auto &it
: node
->attributes
)
596 if (it
.first
!= ID::mem2reg
)
597 reg
->attributes
.emplace(it
.first
, it
.second
->clone());
598 reg
->filename
= node
->filename
;
599 reg
->location
= node
->location
;
600 children
.push_back(reg
);
601 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
605 AstNode
*async_block
= NULL
;
606 while (mem2reg_as_needed_pass2(mem2reg_set
, this, NULL
, async_block
)) { }
608 vector
<AstNode
*> delnodes
;
609 mem2reg_remove(mem2reg_set
, delnodes
);
611 for (auto node
: delnodes
)
615 while (simplify(const_fold
, at_zero
, in_lvalue
, 2, width_hint
, sign_hint
, in_param
)) { }
620 current_filename
= filename
;
622 // we do not look inside a task or function
623 // (but as soon as a task or function is instantiated we process the generated AST as usual)
624 if (type
== AST_FUNCTION
|| type
== AST_TASK
) {
629 // deactivate all calls to non-synthesis system tasks
630 // note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
631 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && (str
== "$strobe" || str
== "$monitor" || str
== "$time" ||
632 str
== "$dumpfile" || str
== "$dumpvars" || str
== "$dumpon" || str
== "$dumpoff" || str
== "$dumpall")) {
633 log_file_warning(filename
, location
.first_line
, "Ignoring call to system %s %s.\n", type
== AST_FCALL
? "function" : "task", str
.c_str());
638 if ((type
== AST_TCALL
) && (str
== "$display" || str
== "$write") && (!current_always
|| current_always
->type
!= AST_INITIAL
)) {
639 log_file_warning(filename
, location
.first_line
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
644 // print messages if this a call to $display() or $write()
645 // This code implements only a small subset of Verilog-2005 $display() format specifiers,
646 // but should be good enough for most uses
647 if ((type
== AST_TCALL
) && ((str
== "$display") || (str
== "$write")))
649 int nargs
= GetSize(children
);
651 log_file_error(filename
, location
.first_line
, "System task `%s' got %d arguments, expected >= 1.\n",
652 str
.c_str(), int(children
.size()));
654 // First argument is the format string
655 AstNode
*node_string
= children
[0];
656 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
657 if (node_string
->type
!= AST_CONSTANT
)
658 log_file_error(filename
, location
.first_line
, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str
.c_str());
659 std::string sformat
= node_string
->bitsAsConst().decode_string();
660 std::string sout
= process_format_str(sformat
, 1, stage
, width_hint
, sign_hint
);
661 // Finally, print the message (only include a \n for $display, not for $write)
662 log("%s", sout
.c_str());
663 if (str
== "$display")
669 // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
670 if (type
== AST_WIRE
|| type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_ENUM_ITEM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_RANGE
|| type
== AST_PREFIX
|| type
== AST_TYPEDEF
)
672 if (type
== AST_IDENTIFIER
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
|| current_scope
[str
]->type
== AST_ENUM_ITEM
))
675 // in certain cases a function must be evaluated constant. this is what in_param controls.
676 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_PREFIX
)
679 std::map
<std::string
, AstNode
*> backup_scope
;
681 // create name resolution entries for all objects with names
682 // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
683 if (type
== AST_MODULE
) {
684 current_scope
.clear();
685 std::map
<std::string
, AstNode
*> this_wire_scope
;
686 for (size_t i
= 0; i
< children
.size(); i
++) {
687 AstNode
*node
= children
[i
];
689 if (node
->type
== AST_WIRE
) {
690 if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
691 for (auto c
: node
->children
[0]->children
) {
692 if (!c
->is_simple_const_expr()) {
693 if (attributes
.count(ID::dynports
))
694 delete attributes
.at(ID::dynports
);
695 attributes
[ID::dynports
] = AstNode::mkconst_int(1, true);
699 if (this_wire_scope
.count(node
->str
) > 0) {
700 AstNode
*first_node
= this_wire_scope
[node
->str
];
701 if (first_node
->is_input
&& node
->is_reg
)
702 goto wires_are_incompatible
;
703 if (!node
->is_input
&& !node
->is_output
&& node
->is_reg
&& node
->children
.size() == 0)
704 goto wires_are_compatible
;
705 if (first_node
->children
.size() == 0 && node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
706 AstNode
*r
= node
->children
[0];
707 if (r
->range_valid
&& r
->range_left
== 0 && r
->range_right
== 0) {
709 node
->children
.pop_back();
712 if (first_node
->children
.size() != node
->children
.size())
713 goto wires_are_incompatible
;
714 for (size_t j
= 0; j
< node
->children
.size(); j
++) {
715 AstNode
*n1
= first_node
->children
[j
], *n2
= node
->children
[j
];
716 if (n1
->type
== AST_RANGE
&& n2
->type
== AST_RANGE
&& n1
->range_valid
&& n2
->range_valid
) {
717 if (n1
->range_left
!= n2
->range_left
)
718 goto wires_are_incompatible
;
719 if (n1
->range_right
!= n2
->range_right
)
720 goto wires_are_incompatible
;
721 } else if (*n1
!= *n2
)
722 goto wires_are_incompatible
;
724 if (first_node
->range_left
!= node
->range_left
)
725 goto wires_are_incompatible
;
726 if (first_node
->range_right
!= node
->range_right
)
727 goto wires_are_incompatible
;
728 if (first_node
->port_id
== 0 && (node
->is_input
|| node
->is_output
))
729 goto wires_are_incompatible
;
730 wires_are_compatible
:
732 first_node
->is_input
= true;
734 first_node
->is_output
= true;
736 first_node
->is_reg
= true;
738 first_node
->is_logic
= true;
740 first_node
->is_signed
= true;
741 for (auto &it
: node
->attributes
) {
742 if (first_node
->attributes
.count(it
.first
) > 0)
743 delete first_node
->attributes
[it
.first
];
744 first_node
->attributes
[it
.first
] = it
.second
->clone();
746 children
.erase(children
.begin()+(i
--));
747 did_something
= true;
750 wires_are_incompatible
:
752 log_file_error(filename
, location
.first_line
, "Incompatible re-declaration of wire %s.\n", node
->str
.c_str());
755 this_wire_scope
[node
->str
] = node
;
757 // these nodes appear at the top level in a module and can define names
758 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
759 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
|| node
->type
== AST_CELL
||
760 node
->type
== AST_TYPEDEF
) {
761 backup_scope
[node
->str
] = current_scope
[node
->str
];
762 current_scope
[node
->str
] = node
;
764 if (node
->type
== AST_ENUM
) {
765 current_scope
[node
->str
] = node
;
766 for (auto enode
: node
->children
) {
767 log_assert(enode
->type
==AST_ENUM_ITEM
);
768 if (current_scope
.count(enode
->str
) == 0)
769 current_scope
[enode
->str
] = enode
;
771 log_file_error(filename
, location
.first_line
, "enum item %s already exists\n", enode
->str
.c_str());
775 for (size_t i
= 0; i
< children
.size(); i
++) {
776 AstNode
*node
= children
[i
];
777 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_MEMORY
|| node
->type
== AST_TYPEDEF
)
778 while (node
->simplify(true, false, false, 1, -1, false, node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
))
779 did_something
= true;
780 if (node
->type
== AST_ENUM
) {
781 for (auto enode
: node
->children
){
782 log_assert(enode
->type
==AST_ENUM_ITEM
);
783 while (node
->simplify(true, false, false, 1, -1, false, in_param
))
784 did_something
= true;
790 // create name resolution entries for all objects with names
791 if (type
== AST_PACKAGE
) {
792 //add names to package scope
793 for (size_t i
= 0; i
< children
.size(); i
++) {
794 AstNode
*node
= children
[i
];
795 // these nodes appear at the top level in a package and can define names
796 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_TYPEDEF
) {
797 current_scope
[node
->str
] = node
;
799 if (node
->type
== AST_ENUM
) {
800 current_scope
[node
->str
] = node
;
801 for (auto enode
: node
->children
) {
802 log_assert(enode
->type
==AST_ENUM_ITEM
);
803 if (current_scope
.count(enode
->str
) == 0)
804 current_scope
[enode
->str
] = enode
;
806 log_file_error(filename
, location
.first_line
, "enum item %s already exists in package\n", enode
->str
.c_str());
813 auto backup_current_block
= current_block
;
814 auto backup_current_block_child
= current_block_child
;
815 auto backup_current_top_block
= current_top_block
;
816 auto backup_current_always
= current_always
;
817 auto backup_current_always_clocked
= current_always_clocked
;
819 if (type
== AST_ALWAYS
|| type
== AST_INITIAL
)
821 if (current_always
!= nullptr)
822 log_file_error(filename
, location
.first_line
, "Invalid nesting of always blocks and/or initializations.\n");
824 current_always
= this;
825 current_always_clocked
= false;
827 if (type
== AST_ALWAYS
)
828 for (auto child
: children
) {
829 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
830 current_always_clocked
= true;
831 if (child
->type
== AST_EDGE
&& GetSize(child
->children
) == 1 &&
832 child
->children
[0]->type
== AST_IDENTIFIER
&& child
->children
[0]->str
== "\\$global_clock")
833 current_always_clocked
= true;
837 int backup_width_hint
= width_hint
;
838 bool backup_sign_hint
= sign_hint
;
840 bool detect_width_simple
= false;
841 bool child_0_is_self_determined
= false;
842 bool child_1_is_self_determined
= false;
843 bool child_2_is_self_determined
= false;
844 bool children_are_self_determined
= false;
845 bool reset_width_after_children
= false;
852 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, true, stage
, -1, false, in_param
) == true)
853 did_something
= true;
854 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
) == true)
855 did_something
= true;
856 children
[0]->detectSignWidth(backup_width_hint
, backup_sign_hint
);
857 children
[1]->detectSignWidth(width_hint
, sign_hint
);
858 width_hint
= max(width_hint
, backup_width_hint
);
859 child_0_is_self_determined
= true;
860 // test only once, before optimizations and memory mappings but after assignment LHS was mapped to an identifier
861 if (children
[0]->id2ast
&& !children
[0]->was_checked
) {
862 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->id2ast
->is_logic
)
863 children
[0]->id2ast
->is_reg
= true; // if logic type is used in a block asignment
864 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && !children
[0]->id2ast
->is_reg
)
865 log_warning("wire '%s' is assigned in a block at %s:%d.%d-%d.%d.\n", children
[0]->str
.c_str(), filename
.c_str(), location
.first_line
, location
.first_column
, location
.last_line
, location
.last_column
);
866 if (type
== AST_ASSIGN
&& children
[0]->id2ast
->is_reg
) {
867 bool is_rand_reg
= false;
868 if (children
[1]->type
== AST_FCALL
) {
869 if (children
[1]->str
== "\\$anyconst")
871 if (children
[1]->str
== "\\$anyseq")
873 if (children
[1]->str
== "\\$allconst")
875 if (children
[1]->str
== "\\$allseq")
879 log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.%d-%d.%d.\n", children
[0]->str
.c_str(), filename
.c_str(), location
.first_line
, location
.first_column
, location
.last_line
, location
.last_column
);
881 children
[0]->was_checked
= true;
888 for (auto *node
: children
) {
889 // resolve any ranges
890 while (!node
->basic_prep
&& node
->simplify(true, false, false, stage
, -1, false, false)) {
891 did_something
= true;
894 // determine member offsets and widths
895 size_packed_struct(this, 0);
897 // instance rather than just a type in a typedef or outer struct?
898 if (!str
.empty() && str
[0] == '\\') {
899 // instance so add a wire for the packed structure
900 auto wnode
= make_packed_struct(this, str
);
901 log_assert(current_ast_mod
);
902 current_ast_mod
->children
.push_back(wnode
);
908 case AST_STRUCT_ITEM
:
912 //log("\nENUM %s: %d child %d\n", str.c_str(), basic_prep, children[0]->basic_prep);
914 for (auto item_node
: children
) {
915 while (!item_node
->basic_prep
&& item_node
->simplify(false, false, false, stage
, -1, false, in_param
))
916 did_something
= true;
918 // allocate values (called more than once)
919 allocateDefaultEnumValues();
925 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, true) == true)
926 did_something
= true;
927 children
[0]->detectSignWidth(width_hint
, sign_hint
);
928 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
929 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, true) == true)
930 did_something
= true;
931 if (!children
[1]->range_valid
)
932 log_file_error(filename
, location
.first_line
, "Non-constant width range on parameter decl.\n");
933 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
937 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, in_param
))
938 did_something
= true;
939 children
[0]->detectSignWidth(width_hint
, sign_hint
);
940 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
941 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
))
942 did_something
= true;
943 if (!children
[1]->range_valid
)
944 log_file_error(filename
, location
.first_line
, "Non-constant width range on enum item decl.\n");
945 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
951 case AST_TO_UNSIGNED
:
959 case AST_REDUCE_XNOR
:
960 case AST_REDUCE_BOOL
:
961 detect_width_simple
= true;
962 children_are_self_determined
= true;
977 detect_width_simple
= true;
981 case AST_SHIFT_RIGHT
:
982 case AST_SHIFT_SLEFT
:
983 case AST_SHIFT_SRIGHT
:
985 detect_width_simple
= true;
986 child_1_is_self_determined
= true;
999 for (auto child
: children
) {
1000 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
1001 did_something
= true;
1002 child
->detectSignWidthWorker(width_hint
, sign_hint
);
1004 reset_width_after_children
= true;
1010 detect_width_simple
= true;
1011 children_are_self_determined
= true;
1015 detect_width_simple
= true;
1016 child_0_is_self_determined
= true;
1020 detect_width_simple
= true;
1021 children_are_self_determined
= true;
1026 children_are_self_determined
= true;
1034 if (detect_width_simple
&& width_hint
< 0) {
1035 if (type
== AST_REPLICATE
)
1036 while (children
[0]->simplify(true, false, in_lvalue
, stage
, -1, false, true) == true)
1037 did_something
= true;
1038 for (auto child
: children
)
1039 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
1040 did_something
= true;
1041 detectSignWidth(width_hint
, sign_hint
);
1044 if (type
== AST_FCALL
&& str
== "\\$past")
1045 detectSignWidth(width_hint
, sign_hint
);
1047 if (type
== AST_TERNARY
) {
1048 int width_hint_left
, width_hint_right
;
1049 bool sign_hint_left
, sign_hint_right
;
1050 bool found_real_left
, found_real_right
;
1051 children
[1]->detectSignWidth(width_hint_left
, sign_hint_left
, &found_real_left
);
1052 children
[2]->detectSignWidth(width_hint_right
, sign_hint_right
, &found_real_right
);
1053 if (found_real_left
|| found_real_right
) {
1054 child_1_is_self_determined
= true;
1055 child_2_is_self_determined
= true;
1059 if (type
== AST_CONDX
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
1060 for (auto &bit
: children
.at(0)->bits
)
1061 if (bit
== State::Sz
|| bit
== State::Sx
)
1065 if (type
== AST_CONDZ
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
1066 for (auto &bit
: children
.at(0)->bits
)
1067 if (bit
== State::Sz
)
1071 if (const_fold
&& type
== AST_CASE
)
1073 while (children
[0]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
1074 if (children
[0]->type
== AST_CONSTANT
&& children
[0]->bits_only_01()) {
1075 std::vector
<AstNode
*> new_children
;
1076 new_children
.push_back(children
[0]);
1077 for (int i
= 1; i
< GetSize(children
); i
++) {
1078 AstNode
*child
= children
[i
];
1079 log_assert(child
->type
== AST_COND
|| child
->type
== AST_CONDX
|| child
->type
== AST_CONDZ
);
1080 for (auto v
: child
->children
) {
1081 if (v
->type
== AST_DEFAULT
)
1082 goto keep_const_cond
;
1083 if (v
->type
== AST_BLOCK
)
1085 while (v
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
1086 if (v
->type
== AST_CONSTANT
&& v
->bits_only_01()) {
1087 if (v
->bits
== children
[0]->bits
) {
1088 while (i
+1 < GetSize(children
))
1089 delete children
[++i
];
1090 goto keep_const_cond
;
1094 goto keep_const_cond
;
1098 new_children
.push_back(child
);
1102 new_children
.swap(children
);
1106 // simplify all children first
1107 // (iterate by index as e.g. auto wires can add new children in the process)
1108 for (size_t i
= 0; i
< children
.size(); i
++) {
1109 bool did_something_here
= true;
1110 bool backup_flag_autowire
= flag_autowire
;
1111 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && i
>= 3)
1113 if ((type
== AST_GENIF
|| type
== AST_GENCASE
) && i
>= 1)
1115 if (type
== AST_GENBLOCK
)
1117 if (type
== AST_BLOCK
&& !str
.empty())
1119 if (type
== AST_PREFIX
&& i
>= 1)
1121 if (type
== AST_DEFPARAM
&& i
== 0)
1122 flag_autowire
= true;
1123 while (did_something_here
&& i
< children
.size()) {
1124 bool const_fold_here
= const_fold
, in_lvalue_here
= in_lvalue
;
1125 int width_hint_here
= width_hint
;
1126 bool sign_hint_here
= sign_hint
;
1127 bool in_param_here
= in_param
;
1128 if (i
== 0 && (type
== AST_REPLICATE
|| type
== AST_WIRE
))
1129 const_fold_here
= true, in_param_here
= true;
1130 if (i
== 0 && (type
== AST_GENIF
|| type
== AST_GENCASE
))
1131 in_param_here
= true;
1132 if (i
== 1 && (type
== AST_FOR
|| type
== AST_GENFOR
))
1133 in_param_here
= true;
1134 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
)
1135 const_fold_here
= true;
1136 if (i
== 0 && (type
== AST_ASSIGN
|| type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
))
1137 in_lvalue_here
= true;
1138 if (type
== AST_BLOCK
) {
1139 current_block
= this;
1140 current_block_child
= children
[i
];
1142 if ((type
== AST_ALWAYS
|| type
== AST_INITIAL
) && children
[i
]->type
== AST_BLOCK
)
1143 current_top_block
= children
[i
];
1144 if (i
== 0 && child_0_is_self_determined
)
1145 width_hint_here
= -1, sign_hint_here
= false;
1146 if (i
== 1 && child_1_is_self_determined
)
1147 width_hint_here
= -1, sign_hint_here
= false;
1148 if (i
== 2 && child_2_is_self_determined
)
1149 width_hint_here
= -1, sign_hint_here
= false;
1150 if (children_are_self_determined
)
1151 width_hint_here
= -1, sign_hint_here
= false;
1152 did_something_here
= children
[i
]->simplify(const_fold_here
, at_zero
, in_lvalue_here
, stage
, width_hint_here
, sign_hint_here
, in_param_here
);
1153 if (did_something_here
)
1154 did_something
= true;
1156 if (stage
== 2 && children
[i
]->type
== AST_INITIAL
&& current_ast_mod
!= this) {
1157 current_ast_mod
->children
.push_back(children
[i
]);
1158 children
.erase(children
.begin() + (i
--));
1159 did_something
= true;
1161 flag_autowire
= backup_flag_autowire
;
1163 for (auto &attr
: attributes
) {
1164 while (attr
.second
->simplify(true, false, false, stage
, -1, false, true))
1165 did_something
= true;
1168 if (reset_width_after_children
) {
1169 width_hint
= backup_width_hint
;
1170 sign_hint
= backup_sign_hint
;
1172 detectSignWidth(width_hint
, sign_hint
);
1175 current_block
= backup_current_block
;
1176 current_block_child
= backup_current_block_child
;
1177 current_top_block
= backup_current_top_block
;
1178 current_always
= backup_current_always
;
1179 current_always_clocked
= backup_current_always_clocked
;
1181 for (auto it
= backup_scope
.begin(); it
!= backup_scope
.end(); it
++) {
1182 if (it
->second
== NULL
)
1183 current_scope
.erase(it
->first
);
1185 current_scope
[it
->first
] = it
->second
;
1188 current_filename
= filename
;
1190 if (type
== AST_MODULE
)
1191 current_scope
.clear();
1193 // convert defparam nodes to cell parameters
1194 if (type
== AST_DEFPARAM
&& !children
.empty())
1196 if (children
[0]->type
!= AST_IDENTIFIER
)
1197 log_file_error(filename
, location
.first_line
, "Module name in defparam contains non-constant expressions!\n");
1199 string modname
, paramname
= children
[0]->str
;
1201 size_t pos
= paramname
.rfind('.');
1203 while (pos
!= 0 && pos
!= std::string::npos
)
1205 modname
= paramname
.substr(0, pos
);
1207 if (current_scope
.count(modname
))
1210 pos
= paramname
.rfind('.', pos
- 1);
1213 if (pos
== std::string::npos
)
1214 log_file_error(filename
, location
.first_line
, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname
).c_str());
1216 paramname
= "\\" + paramname
.substr(pos
+1);
1218 if (current_scope
.at(modname
)->type
!= AST_CELL
)
1219 log_file_error(filename
, location
.first_line
, "Defparam argument `%s . %s` does not match a cell!\n",
1220 RTLIL::unescape_id(modname
).c_str(), RTLIL::unescape_id(paramname
).c_str());
1222 AstNode
*paraset
= new AstNode(AST_PARASET
, children
[1]->clone(), GetSize(children
) > 2 ? children
[2]->clone() : NULL
);
1223 paraset
->str
= paramname
;
1225 AstNode
*cell
= current_scope
.at(modname
);
1226 cell
->children
.insert(cell
->children
.begin() + 1, paraset
);
1231 if (type
== AST_TYPEDEF
) {
1232 log_assert(children
.size() == 1);
1233 auto type_node
= children
[0];
1234 log_assert(type_node
->type
== AST_WIRE
|| type_node
->type
== AST_MEMORY
|| type_node
->type
== AST_STRUCT
|| type_node
->type
== AST_UNION
);
1235 while (type_node
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {
1236 did_something
= true;
1238 log_assert(!type_node
->is_custom_type
);
1241 // resolve types of wires
1242 if (type
== AST_WIRE
|| type
== AST_MEMORY
) {
1243 if (is_custom_type
) {
1244 log_assert(children
.size() >= 1);
1245 log_assert(children
[0]->type
== AST_WIRETYPE
);
1246 auto type_name
= children
[0]->str
;
1247 if (!current_scope
.count(type_name
)) {
1248 log_file_error(filename
, location
.first_line
, "Unknown identifier `%s' used as type name\n", type_name
.c_str());
1250 AstNode
*resolved_type_node
= current_scope
.at(type_name
);
1251 if (resolved_type_node
->type
!= AST_TYPEDEF
)
1252 log_file_error(filename
, location
.first_line
, "`%s' does not name a type\n", type_name
.c_str());
1253 log_assert(resolved_type_node
->children
.size() == 1);
1254 AstNode
*template_node
= resolved_type_node
->children
[0];
1256 // Ensure typedef itself is fully simplified
1257 while (template_node
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
1259 if (template_node
->type
== AST_STRUCT
|| template_node
->type
== AST_UNION
) {
1260 // replace with wire representing the packed structure
1261 newNode
= make_packed_struct(template_node
, str
);
1262 current_scope
[str
] = this;
1266 // Remove type reference
1268 children
.erase(children
.begin());
1270 if (type
== AST_WIRE
)
1271 type
= template_node
->type
;
1272 is_reg
= template_node
->is_reg
;
1273 is_logic
= template_node
->is_logic
;
1274 is_signed
= template_node
->is_signed
;
1275 is_string
= template_node
->is_string
;
1276 is_custom_type
= template_node
->is_custom_type
;
1278 range_valid
= template_node
->range_valid
;
1279 range_swapped
= template_node
->range_swapped
;
1280 range_left
= template_node
->range_left
;
1281 range_right
= template_node
->range_right
;
1283 attributes
[ID::wiretype
] = mkconst_str(resolved_type_node
->str
);
1285 // if an enum then add attributes to support simulator tracing
1286 annotateTypedEnums(template_node
);
1288 // Insert clones children from template at beginning
1289 for (int i
= 0; i
< GetSize(template_node
->children
); i
++)
1290 children
.insert(children
.begin() + i
, template_node
->children
[i
]->clone());
1292 if (type
== AST_MEMORY
&& GetSize(children
) == 1) {
1293 // Single-bit memories must have [0:0] range
1294 AstNode
*rng
= make_range(0, 0);
1295 children
.insert(children
.begin(), rng
);
1297 did_something
= true;
1299 log_assert(!is_custom_type
);
1302 // resolve types of parameters
1303 if (type
== AST_LOCALPARAM
|| type
== AST_PARAMETER
) {
1304 if (is_custom_type
) {
1305 log_assert(children
.size() == 2);
1306 log_assert(children
[1]->type
== AST_WIRETYPE
);
1307 if (!current_scope
.count(children
[1]->str
))
1308 log_file_error(filename
, location
.first_line
, "Unknown identifier `%s' used as type name\n", children
[1]->str
.c_str());
1309 AstNode
*resolved_type_node
= current_scope
.at(children
[1]->str
);
1310 if (resolved_type_node
->type
!= AST_TYPEDEF
)
1311 log_file_error(filename
, location
.first_line
, "`%s' does not name a type\n", children
[1]->str
.c_str());
1312 log_assert(resolved_type_node
->children
.size() == 1);
1313 AstNode
*template_node
= resolved_type_node
->children
[0];
1315 children
.pop_back();
1317 // Ensure typedef itself is fully simplified
1318 while(template_node
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
1320 if (template_node
->type
== AST_MEMORY
)
1321 log_file_error(filename
, location
.first_line
, "unpacked array type `%s' cannot be used for a parameter\n", children
[1]->str
.c_str());
1322 is_signed
= template_node
->is_signed
;
1323 is_string
= template_node
->is_string
;
1324 is_custom_type
= template_node
->is_custom_type
;
1326 range_valid
= template_node
->range_valid
;
1327 range_swapped
= template_node
->range_swapped
;
1328 range_left
= template_node
->range_left
;
1329 range_right
= template_node
->range_right
;
1330 attributes
[ID::wiretype
] = mkconst_str(resolved_type_node
->str
);
1331 for (auto template_child
: template_node
->children
)
1332 children
.push_back(template_child
->clone());
1333 did_something
= true;
1335 log_assert(!is_custom_type
);
1338 // resolve constant prefixes
1339 if (type
== AST_PREFIX
) {
1340 if (children
[0]->type
!= AST_CONSTANT
) {
1341 // dumpAst(NULL, "> ");
1342 log_file_error(filename
, location
.first_line
, "Index in generate block prefix syntax is not constant!\n");
1344 if (children
[1]->type
== AST_PREFIX
)
1345 children
[1]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
);
1346 log_assert(children
[1]->type
== AST_IDENTIFIER
);
1347 newNode
= children
[1]->clone();
1348 const char *second_part
= children
[1]->str
.c_str();
1349 if (second_part
[0] == '\\')
1351 newNode
->str
= stringf("%s[%d].%s", str
.c_str(), children
[0]->integer
, second_part
);
1355 // evaluate TO_BITS nodes
1356 if (type
== AST_TO_BITS
) {
1357 if (children
[0]->type
!= AST_CONSTANT
)
1358 log_file_error(filename
, location
.first_line
, "Left operand of to_bits expression is not constant!\n");
1359 if (children
[1]->type
!= AST_CONSTANT
)
1360 log_file_error(filename
, location
.first_line
, "Right operand of to_bits expression is not constant!\n");
1361 RTLIL::Const new_value
= children
[1]->bitsAsConst(children
[0]->bitsAsConst().as_int(), children
[1]->is_signed
);
1362 newNode
= mkconst_bits(new_value
.bits
, children
[1]->is_signed
);
1366 // annotate constant ranges
1367 if (type
== AST_RANGE
) {
1368 bool old_range_valid
= range_valid
;
1369 range_valid
= false;
1370 range_swapped
= false;
1373 log_assert(children
.size() >= 1);
1374 if (children
[0]->type
== AST_CONSTANT
) {
1376 range_left
= children
[0]->integer
;
1377 if (children
.size() == 1)
1378 range_right
= range_left
;
1380 if (children
.size() >= 2) {
1381 if (children
[1]->type
== AST_CONSTANT
)
1382 range_right
= children
[1]->integer
;
1384 range_valid
= false;
1386 if (old_range_valid
!= range_valid
)
1387 did_something
= true;
1388 if (range_valid
&& range_right
> range_left
) {
1389 int tmp
= range_right
;
1390 range_right
= range_left
;
1392 range_swapped
= true;
1396 // annotate wires with their ranges
1397 if (type
== AST_WIRE
) {
1398 if (children
.size() > 0) {
1399 if (children
[0]->range_valid
) {
1401 did_something
= true;
1403 range_swapped
= children
[0]->range_swapped
;
1404 range_left
= children
[0]->range_left
;
1405 range_right
= children
[0]->range_right
;
1406 bool force_upto
= false, force_downto
= false;
1407 if (attributes
.count(ID::force_upto
)) {
1408 AstNode
*val
= attributes
[ID::force_upto
];
1409 if (val
->type
!= AST_CONSTANT
)
1410 log_file_error(filename
, location
.first_line
, "Attribute `force_upto' with non-constant value!\n");
1411 force_upto
= val
->asAttrConst().as_bool();
1413 if (attributes
.count(ID::force_downto
)) {
1414 AstNode
*val
= attributes
[ID::force_downto
];
1415 if (val
->type
!= AST_CONSTANT
)
1416 log_file_error(filename
, location
.first_line
, "Attribute `force_downto' with non-constant value!\n");
1417 force_downto
= val
->asAttrConst().as_bool();
1419 if (force_upto
&& force_downto
)
1420 log_file_error(filename
, location
.first_line
, "Attributes `force_downto' and `force_upto' cannot be both set!\n");
1421 if ((force_upto
&& !range_swapped
) || (force_downto
&& range_swapped
)) {
1422 std::swap(range_left
, range_right
);
1423 range_swapped
= force_upto
;
1428 did_something
= true;
1430 range_swapped
= false;
1436 // resolve multiranges on memory decl
1437 if (type
== AST_MEMORY
&& children
.size() > 1 && children
[1]->type
== AST_MULTIRANGE
)
1440 multirange_dimensions
.clear();
1441 for (auto range
: children
[1]->children
) {
1442 if (!range
->range_valid
)
1443 log_file_error(filename
, location
.first_line
, "Non-constant range on memory decl.\n");
1444 multirange_dimensions
.push_back(min(range
->range_left
, range
->range_right
));
1445 multirange_dimensions
.push_back(max(range
->range_left
, range
->range_right
) - min(range
->range_left
, range
->range_right
) + 1);
1446 total_size
*= multirange_dimensions
.back();
1449 children
[1] = new AstNode(AST_RANGE
, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size
-1, true));
1450 did_something
= true;
1453 // resolve multiranges on memory access
1454 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
&& children
.size() > 0 && children
[0]->type
== AST_MULTIRANGE
)
1456 AstNode
*index_expr
= nullptr;
1458 for (int i
= 0; 2*i
< GetSize(id2ast
->multirange_dimensions
); i
++)
1460 if (GetSize(children
[0]->children
) < i
)
1461 log_file_error(filename
, location
.first_line
, "Insufficient number of array indices for %s.\n", log_id(str
));
1463 AstNode
*new_index_expr
= children
[0]->children
[i
]->children
.at(0)->clone();
1465 if (id2ast
->multirange_dimensions
[2*i
])
1466 new_index_expr
= new AstNode(AST_SUB
, new_index_expr
, AstNode::mkconst_int(id2ast
->multirange_dimensions
[2*i
], true));
1469 index_expr
= new_index_expr
;
1471 index_expr
= new AstNode(AST_ADD
, new AstNode(AST_MUL
, index_expr
, AstNode::mkconst_int(id2ast
->multirange_dimensions
[2*i
+1], true)), new_index_expr
);
1474 for (int i
= GetSize(id2ast
->multirange_dimensions
)/2; i
< GetSize(children
[0]->children
); i
++)
1475 children
.push_back(children
[0]->children
[i
]->clone());
1478 if (index_expr
== nullptr)
1479 children
.erase(children
.begin());
1481 children
[0] = new AstNode(AST_RANGE
, index_expr
);
1483 did_something
= true;
1486 // trim/extend parameters
1487 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_ENUM_ITEM
) {
1488 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
1489 if (!children
[1]->range_valid
)
1490 log_file_error(filename
, location
.first_line
, "Non-constant width range on parameter decl.\n");
1491 int width
= std::abs(children
[1]->range_left
- children
[1]->range_right
) + 1;
1492 if (children
[0]->type
== AST_REALVALUE
) {
1493 RTLIL::Const constvalue
= children
[0]->realAsConst(width
);
1494 log_file_warning(filename
, location
.first_line
, "converting real value %e to binary %s.\n",
1495 children
[0]->realvalue
, log_signal(constvalue
));
1497 children
[0] = mkconst_bits(constvalue
.bits
, sign_hint
);
1498 did_something
= true;
1500 if (children
[0]->type
== AST_CONSTANT
) {
1501 if (width
!= int(children
[0]->bits
.size())) {
1502 RTLIL::SigSpec
sig(children
[0]->bits
);
1503 sig
.extend_u0(width
, children
[0]->is_signed
);
1504 AstNode
*old_child_0
= children
[0];
1505 children
[0] = mkconst_bits(sig
.as_const().bits
, is_signed
);
1508 children
[0]->is_signed
= is_signed
;
1511 range_swapped
= children
[1]->range_swapped
;
1512 range_left
= children
[1]->range_left
;
1513 range_right
= children
[1]->range_right
;
1515 if (children
.size() > 1 && children
[1]->type
== AST_REALVALUE
&& children
[0]->type
== AST_CONSTANT
) {
1516 double as_realvalue
= children
[0]->asReal(sign_hint
);
1518 children
[0] = new AstNode(AST_REALVALUE
);
1519 children
[0]->realvalue
= as_realvalue
;
1520 did_something
= true;
1524 if (type
== AST_IDENTIFIER
&& !basic_prep
) {
1525 // check if a plausible struct member sss.mmmm
1527 if (name_has_dot(str
, sname
)) {
1528 if (current_scope
.count(str
) > 0) {
1529 auto item_node
= current_scope
[str
];
1530 if (item_node
->type
== AST_STRUCT_ITEM
) {
1531 // structure member, rewrite this node to reference the packed struct wire
1532 auto range
= make_struct_member_range(this, item_node
);
1533 newNode
= new AstNode(AST_IDENTIFIER
, range
);
1534 newNode
->str
= sname
;
1535 newNode
->basic_prep
= true;
1541 // annotate identifiers using scope resolution and create auto-wires as needed
1542 if (type
== AST_IDENTIFIER
) {
1543 if (current_scope
.count(str
) == 0) {
1544 AstNode
*current_scope_ast
= (current_ast_mod
== nullptr) ? current_ast
: current_ast_mod
;
1545 for (auto node
: current_scope_ast
->children
) {
1546 //log("looking at mod scope child %s\n", type2str(node->type).c_str());
1547 switch (node
->type
) {
1549 case AST_LOCALPARAM
:
1556 case AST_DPI_FUNCTION
:
1557 //log("found child %s, %s\n", type2str(node->type).c_str(), node->str.c_str());
1558 if (str
== node
->str
) {
1559 //log("add %s, type %s to scope\n", str.c_str(), type2str(node->type).c_str());
1560 current_scope
[node
->str
] = node
;
1564 current_scope
[node
->str
] = node
;
1565 for (auto enum_node
: node
->children
) {
1566 log_assert(enum_node
->type
==AST_ENUM_ITEM
);
1567 if (str
== enum_node
->str
) {
1568 //log("\nadding enum item %s to scope\n", str.c_str());
1569 current_scope
[str
] = enum_node
;
1578 if (current_scope
.count(str
) == 0) {
1579 if (current_ast_mod
== nullptr) {
1580 log_file_error(filename
, location
.first_line
, "Identifier `%s' is implicitly declared outside of a module.\n", str
.c_str());
1581 } else if (flag_autowire
|| str
== "\\$global_clock") {
1582 AstNode
*auto_wire
= new AstNode(AST_AUTOWIRE
);
1583 auto_wire
->str
= str
;
1584 current_ast_mod
->children
.push_back(auto_wire
);
1585 current_scope
[str
] = auto_wire
;
1586 did_something
= true;
1588 log_file_error(filename
, location
.first_line
, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str
.c_str());
1591 if (id2ast
!= current_scope
[str
]) {
1592 id2ast
= current_scope
[str
];
1593 did_something
= true;
1597 // split memory access with bit select to individual statements
1598 if (type
== AST_IDENTIFIER
&& children
.size() == 2 && children
[0]->type
== AST_RANGE
&& children
[1]->type
== AST_RANGE
&& !in_lvalue
)
1600 if (id2ast
== NULL
|| id2ast
->type
!= AST_MEMORY
|| children
[0]->children
.size() != 1)
1601 log_file_error(filename
, location
.first_line
, "Invalid bit-select on memory access!\n");
1603 int mem_width
, mem_size
, addr_bits
;
1604 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
1606 int data_range_left
= id2ast
->children
[0]->range_left
;
1607 int data_range_right
= id2ast
->children
[0]->range_right
;
1609 if (id2ast
->children
[0]->range_swapped
)
1610 std::swap(data_range_left
, data_range_right
);
1612 std::stringstream sstr
;
1613 sstr
<< "$mem2bits$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
1614 std::string wire_id
= sstr
.str();
1616 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
1617 wire
->str
= wire_id
;
1619 wire
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
1620 current_ast_mod
->children
.push_back(wire
);
1621 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
1623 AstNode
*data
= clone();
1624 delete data
->children
[1];
1625 data
->children
.pop_back();
1627 AstNode
*assign
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), data
);
1628 assign
->children
[0]->str
= wire_id
;
1629 assign
->children
[0]->was_checked
= true;
1633 size_t assign_idx
= 0;
1634 while (assign_idx
< current_block
->children
.size() && current_block
->children
[assign_idx
] != current_block_child
)
1636 log_assert(assign_idx
< current_block
->children
.size());
1637 current_block
->children
.insert(current_block
->children
.begin()+assign_idx
, assign
);
1638 wire
->is_reg
= true;
1642 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
1643 proc
->children
[0]->children
.push_back(assign
);
1644 current_ast_mod
->children
.push_back(proc
);
1647 newNode
= new AstNode(AST_IDENTIFIER
, children
[1]->clone());
1648 newNode
->str
= wire_id
;
1649 newNode
->id2ast
= wire
;
1653 if (type
== AST_WHILE
)
1654 log_file_error(filename
, location
.first_line
, "While loops are only allowed in constant functions!\n");
1656 if (type
== AST_REPEAT
)
1658 AstNode
*count
= children
[0];
1659 AstNode
*body
= children
[1];
1661 // eval count expression
1662 while (count
->simplify(true, false, false, stage
, 32, true, false)) { }
1664 if (count
->type
!= AST_CONSTANT
)
1665 log_file_error(filename
, location
.first_line
, "Repeat loops outside must have constant repeat counts!\n");
1667 // convert to a block with the body repeated n times
1670 for (int i
= 0; i
< count
->bitsAsConst().as_int(); i
++)
1671 children
.insert(children
.begin(), body
->clone());
1675 did_something
= true;
1678 // unroll for loops and generate-for blocks
1679 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && children
.size() != 0)
1681 AstNode
*init_ast
= children
[0];
1682 AstNode
*while_ast
= children
[1];
1683 AstNode
*next_ast
= children
[2];
1684 AstNode
*body_ast
= children
[3];
1686 while (body_ast
->type
== AST_GENBLOCK
&& body_ast
->str
.empty() &&
1687 body_ast
->children
.size() == 1 && body_ast
->children
.at(0)->type
== AST_GENBLOCK
)
1688 body_ast
= body_ast
->children
.at(0);
1690 if (init_ast
->type
!= AST_ASSIGN_EQ
)
1691 log_file_error(filename
, location
.first_line
, "Unsupported 1st expression of generate for-loop!\n");
1692 if (next_ast
->type
!= AST_ASSIGN_EQ
)
1693 log_file_error(filename
, location
.first_line
, "Unsupported 3rd expression of generate for-loop!\n");
1695 if (type
== AST_GENFOR
) {
1696 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
1697 log_file_error(filename
, location
.first_line
, "Left hand side of 1st expression of generate for-loop is not a gen var!\n");
1698 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
1699 log_file_error(filename
, location
.first_line
, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n");
1701 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1702 log_file_error(filename
, location
.first_line
, "Left hand side of 1st expression of generate for-loop is not a register!\n");
1703 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1704 log_file_error(filename
, location
.first_line
, "Left hand side of 3rd expression of generate for-loop is not a register!\n");
1707 if (init_ast
->children
[0]->id2ast
!= next_ast
->children
[0]->id2ast
)
1708 log_file_error(filename
, location
.first_line
, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n");
1710 // eval 1st expression
1711 AstNode
*varbuf
= init_ast
->children
[1]->clone();
1713 int expr_width_hint
= -1;
1714 bool expr_sign_hint
= true;
1715 varbuf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1716 while (varbuf
->simplify(true, false, false, stage
, 32, true, false)) { }
1719 if (varbuf
->type
!= AST_CONSTANT
)
1720 log_file_error(filename
, location
.first_line
, "Right hand side of 1st expression of generate for-loop is not constant!\n");
1722 auto resolved
= current_scope
.at(init_ast
->children
[0]->str
);
1723 if (resolved
->range_valid
) {
1724 int const_size
= varbuf
->range_left
- varbuf
->range_right
;
1725 int resolved_size
= resolved
->range_left
- resolved
->range_right
;
1726 if (const_size
< resolved_size
) {
1727 for (int i
= const_size
; i
< resolved_size
; i
++)
1728 varbuf
->bits
.push_back(resolved
->is_signed
? varbuf
->bits
.back() : State::S0
);
1729 varbuf
->range_left
= resolved
->range_left
;
1730 varbuf
->range_right
= resolved
->range_right
;
1731 varbuf
->range_swapped
= resolved
->range_swapped
;
1732 varbuf
->range_valid
= resolved
->range_valid
;
1736 varbuf
= new AstNode(AST_LOCALPARAM
, varbuf
);
1737 varbuf
->str
= init_ast
->children
[0]->str
;
1739 AstNode
*backup_scope_varbuf
= current_scope
[varbuf
->str
];
1740 current_scope
[varbuf
->str
] = varbuf
;
1742 size_t current_block_idx
= 0;
1743 if (type
== AST_FOR
) {
1744 while (current_block_idx
< current_block
->children
.size() &&
1745 current_block
->children
[current_block_idx
] != current_block_child
)
1746 current_block_idx
++;
1751 // eval 2nd expression
1752 AstNode
*buf
= while_ast
->clone();
1754 int expr_width_hint
= -1;
1755 bool expr_sign_hint
= true;
1756 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1757 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, false)) { }
1760 if (buf
->type
!= AST_CONSTANT
)
1761 log_file_error(filename
, location
.first_line
, "2nd expression of generate for-loop is not constant!\n");
1763 if (buf
->integer
== 0) {
1770 int index
= varbuf
->children
[0]->integer
;
1771 if (body_ast
->type
== AST_GENBLOCK
)
1772 buf
= body_ast
->clone();
1774 buf
= new AstNode(AST_GENBLOCK
, body_ast
->clone());
1775 if (buf
->str
.empty()) {
1776 std::stringstream sstr
;
1777 sstr
<< "$genblock$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
1778 buf
->str
= sstr
.str();
1780 std::map
<std::string
, std::string
> name_map
;
1781 std::stringstream sstr
;
1782 sstr
<< buf
->str
<< "[" << index
<< "].";
1783 buf
->expand_genblock(varbuf
->str
, sstr
.str(), name_map
);
1785 if (type
== AST_GENFOR
) {
1786 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1787 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1788 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1791 for (size_t i
= 0; i
< buf
->children
.size(); i
++)
1792 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
->children
[i
]);
1794 buf
->children
.clear();
1797 // eval 3rd expression
1798 buf
= next_ast
->children
[1]->clone();
1800 int expr_width_hint
= -1;
1801 bool expr_sign_hint
= true;
1802 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1803 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, true)) { }
1806 if (buf
->type
!= AST_CONSTANT
)
1807 log_file_error(filename
, location
.first_line
, "Right hand side of 3rd expression of generate for-loop is not constant (%s)!\n", type2str(buf
->type
).c_str());
1809 delete varbuf
->children
[0];
1810 varbuf
->children
[0] = buf
;
1813 if (type
== AST_FOR
) {
1814 AstNode
*buf
= next_ast
->clone();
1815 delete buf
->children
[1];
1816 buf
->children
[1] = varbuf
->children
[0]->clone();
1817 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
);
1820 current_scope
[varbuf
->str
] = backup_scope_varbuf
;
1823 did_something
= true;
1826 // check for local objects in unnamed block
1827 if (type
== AST_BLOCK
&& str
.empty())
1829 for (size_t i
= 0; i
< children
.size(); i
++)
1830 if (children
[i
]->type
== AST_WIRE
|| children
[i
]->type
== AST_MEMORY
|| children
[i
]->type
== AST_PARAMETER
|| children
[i
]->type
== AST_LOCALPARAM
|| children
[i
]->type
== AST_TYPEDEF
)
1831 log_file_error(children
[i
]->filename
, children
[i
]->location
.first_line
, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
1834 // transform block with name
1835 if (type
== AST_BLOCK
&& !str
.empty())
1837 std::map
<std::string
, std::string
> name_map
;
1838 expand_genblock(std::string(), str
+ ".", name_map
);
1840 std::vector
<AstNode
*> new_children
;
1841 for (size_t i
= 0; i
< children
.size(); i
++)
1842 if (children
[i
]->type
== AST_WIRE
|| children
[i
]->type
== AST_MEMORY
|| children
[i
]->type
== AST_PARAMETER
|| children
[i
]->type
== AST_LOCALPARAM
|| children
[i
]->type
== AST_TYPEDEF
) {
1843 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1844 current_ast_mod
->children
.push_back(children
[i
]);
1845 current_scope
[children
[i
]->str
] = children
[i
];
1847 new_children
.push_back(children
[i
]);
1849 children
.swap(new_children
);
1850 did_something
= true;
1854 // simplify unconditional generate block
1855 if (type
== AST_GENBLOCK
&& children
.size() != 0)
1858 std::map
<std::string
, std::string
> name_map
;
1859 expand_genblock(std::string(), str
+ ".", name_map
);
1862 for (size_t i
= 0; i
< children
.size(); i
++) {
1863 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1864 current_ast_mod
->children
.push_back(children
[i
]);
1868 did_something
= true;
1871 // simplify generate-if blocks
1872 if (type
== AST_GENIF
&& children
.size() != 0)
1874 AstNode
*buf
= children
[0]->clone();
1875 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1876 if (buf
->type
!= AST_CONSTANT
) {
1877 // for (auto f : log_files)
1878 // dumpAst(f, "verilog-ast> ");
1879 log_file_error(filename
, location
.first_line
, "Condition for generate if is not constant!\n");
1881 if (buf
->asBool() != 0) {
1883 buf
= children
[1]->clone();
1886 buf
= children
.size() > 2 ? children
[2]->clone() : NULL
;
1891 if (buf
->type
!= AST_GENBLOCK
)
1892 buf
= new AstNode(AST_GENBLOCK
, buf
);
1894 if (!buf
->str
.empty()) {
1895 std::map
<std::string
, std::string
> name_map
;
1896 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1899 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1900 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1901 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1904 buf
->children
.clear();
1909 did_something
= true;
1912 // simplify generate-case blocks
1913 if (type
== AST_GENCASE
&& children
.size() != 0)
1915 AstNode
*buf
= children
[0]->clone();
1916 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1917 if (buf
->type
!= AST_CONSTANT
) {
1918 // for (auto f : log_files)
1919 // dumpAst(f, "verilog-ast> ");
1920 log_file_error(filename
, location
.first_line
, "Condition for generate case is not constant!\n");
1923 bool ref_signed
= buf
->is_signed
;
1924 RTLIL::Const ref_value
= buf
->bitsAsConst();
1927 AstNode
*selected_case
= NULL
;
1928 for (size_t i
= 1; i
< children
.size(); i
++)
1930 log_assert(children
.at(i
)->type
== AST_COND
|| children
.at(i
)->type
== AST_CONDX
|| children
.at(i
)->type
== AST_CONDZ
);
1932 AstNode
*this_genblock
= NULL
;
1933 for (auto child
: children
.at(i
)->children
) {
1934 log_assert(this_genblock
== NULL
);
1935 if (child
->type
== AST_GENBLOCK
)
1936 this_genblock
= child
;
1939 for (auto child
: children
.at(i
)->children
)
1941 if (child
->type
== AST_DEFAULT
) {
1942 if (selected_case
== NULL
)
1943 selected_case
= this_genblock
;
1946 if (child
->type
== AST_GENBLOCK
)
1949 buf
= child
->clone();
1950 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, true)) { }
1951 if (buf
->type
!= AST_CONSTANT
) {
1952 // for (auto f : log_files)
1953 // dumpAst(f, "verilog-ast> ");
1954 log_file_error(filename
, location
.first_line
, "Expression in generate case is not constant!\n");
1957 bool is_selected
= RTLIL::const_eq(ref_value
, buf
->bitsAsConst(), ref_signed
&& buf
->is_signed
, ref_signed
&& buf
->is_signed
, 1).as_bool();
1961 selected_case
= this_genblock
;
1962 i
= children
.size();
1968 if (selected_case
!= NULL
)
1970 log_assert(selected_case
->type
== AST_GENBLOCK
);
1971 buf
= selected_case
->clone();
1973 if (!buf
->str
.empty()) {
1974 std::map
<std::string
, std::string
> name_map
;
1975 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1978 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1979 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1980 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1983 buf
->children
.clear();
1988 did_something
= true;
1991 // unroll cell arrays
1992 if (type
== AST_CELLARRAY
)
1994 if (!children
.at(0)->range_valid
)
1995 log_file_error(filename
, location
.first_line
, "Non-constant array range on cell array.\n");
1997 newNode
= new AstNode(AST_GENBLOCK
);
1998 int num
= max(children
.at(0)->range_left
, children
.at(0)->range_right
) - min(children
.at(0)->range_left
, children
.at(0)->range_right
) + 1;
2000 for (int i
= 0; i
< num
; i
++) {
2001 int idx
= children
.at(0)->range_left
> children
.at(0)->range_right
? children
.at(0)->range_right
+ i
: children
.at(0)->range_right
- i
;
2002 AstNode
*new_cell
= children
.at(1)->clone();
2003 newNode
->children
.push_back(new_cell
);
2004 new_cell
->str
+= stringf("[%d]", idx
);
2005 if (new_cell
->type
== AST_PRIMITIVE
) {
2006 log_file_error(filename
, location
.first_line
, "Cell arrays of primitives are currently not supported.\n");
2008 log_assert(new_cell
->children
.at(0)->type
== AST_CELLTYPE
);
2009 new_cell
->children
.at(0)->str
= stringf("$array:%d:%d:%s", i
, num
, new_cell
->children
.at(0)->str
.c_str());
2016 // replace primitives with assignments
2017 if (type
== AST_PRIMITIVE
)
2019 if (children
.size() < 2)
2020 log_file_error(filename
, location
.first_line
, "Insufficient number of arguments for primitive `%s'!\n", str
.c_str());
2022 std::vector
<AstNode
*> children_list
;
2023 for (auto child
: children
) {
2024 log_assert(child
->type
== AST_ARGUMENT
);
2025 log_assert(child
->children
.size() == 1);
2026 children_list
.push_back(child
->children
[0]);
2027 child
->children
.clear();
2032 if (str
== "bufif0" || str
== "bufif1" || str
== "notif0" || str
== "notif1")
2034 if (children_list
.size() != 3)
2035 log_file_error(filename
, location
.first_line
, "Invalid number of arguments for primitive `%s'!\n", str
.c_str());
2037 std::vector
<RTLIL::State
> z_const(1, RTLIL::State::Sz
);
2039 AstNode
*mux_input
= children_list
.at(1);
2040 if (str
== "notif0" || str
== "notif1") {
2041 mux_input
= new AstNode(AST_BIT_NOT
, mux_input
);
2043 AstNode
*node
= new AstNode(AST_TERNARY
, children_list
.at(2));
2044 if (str
== "bufif0") {
2045 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
2046 node
->children
.push_back(mux_input
);
2048 node
->children
.push_back(mux_input
);
2049 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
2054 children
.push_back(children_list
.at(0));
2055 children
.back()->was_checked
= true;
2056 children
.push_back(node
);
2057 did_something
= true;
2061 AstNodeType op_type
= AST_NONE
;
2062 bool invert_results
= false;
2065 op_type
= AST_BIT_AND
;
2067 op_type
= AST_BIT_AND
, invert_results
= true;
2069 op_type
= AST_BIT_OR
;
2071 op_type
= AST_BIT_OR
, invert_results
= true;
2073 op_type
= AST_BIT_XOR
;
2075 op_type
= AST_BIT_XOR
, invert_results
= true;
2079 op_type
= AST_POS
, invert_results
= true;
2080 log_assert(op_type
!= AST_NONE
);
2082 AstNode
*node
= children_list
[1];
2083 if (op_type
!= AST_POS
)
2084 for (size_t i
= 2; i
< children_list
.size(); i
++) {
2085 node
= new AstNode(op_type
, node
, children_list
[i
]);
2086 node
->location
= location
;
2089 node
= new AstNode(AST_BIT_NOT
, node
);
2093 children
.push_back(children_list
[0]);
2094 children
.back()->was_checked
= true;
2095 children
.push_back(node
);
2096 did_something
= true;
2100 // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
2101 // either a big case block that selects the correct single-bit assignment, or mask and
2102 // shift operations.
2103 if (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
)
2105 if (children
[0]->type
!= AST_IDENTIFIER
|| children
[0]->children
.size() == 0)
2106 goto skip_dynamic_range_lvalue_expansion
;
2107 if (children
[0]->children
[0]->range_valid
|| did_something
)
2108 goto skip_dynamic_range_lvalue_expansion
;
2109 if (children
[0]->id2ast
== NULL
|| children
[0]->id2ast
->type
!= AST_WIRE
)
2110 goto skip_dynamic_range_lvalue_expansion
;
2111 if (!children
[0]->id2ast
->range_valid
)
2112 goto skip_dynamic_range_lvalue_expansion
;
2114 int source_width
= children
[0]->id2ast
->range_left
- children
[0]->id2ast
->range_right
+ 1;
2115 int result_width
= 1;
2117 AstNode
*shift_expr
= NULL
;
2118 AstNode
*range
= children
[0]->children
[0];
2120 if (range
->children
.size() == 1) {
2121 shift_expr
= range
->children
[0]->clone();
2123 shift_expr
= range
->children
[1]->clone();
2124 AstNode
*left_at_zero_ast
= range
->children
[0]->clone();
2125 AstNode
*right_at_zero_ast
= range
->children
[1]->clone();
2126 while (left_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
2127 while (right_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
2128 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
2129 log_file_error(filename
, location
.first_line
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
2130 result_width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
2133 bool use_case_method
= false;
2135 if (children
[0]->id2ast
->attributes
.count(ID::nowrshmsk
)) {
2136 AstNode
*node
= children
[0]->id2ast
->attributes
.at(ID::nowrshmsk
);
2137 while (node
->simplify(true, false, false, stage
, -1, false, false)) { }
2138 if (node
->type
!= AST_CONSTANT
)
2139 log_file_error(filename
, location
.first_line
, "Non-constant value for `nowrshmsk' attribute on `%s'!\n", children
[0]->id2ast
->str
.c_str());
2140 if (node
->asAttrConst().as_bool())
2141 use_case_method
= true;
2144 if (!use_case_method
&& current_always
->detect_latch(children
[0]->str
))
2145 use_case_method
= true;
2147 if (use_case_method
)
2151 did_something
= true;
2152 newNode
= new AstNode(AST_CASE
, shift_expr
);
2153 for (int i
= 0; i
< source_width
; i
++) {
2154 int start_bit
= children
[0]->id2ast
->range_right
+ i
;
2155 int end_bit
= std::min(start_bit
+result_width
,source_width
) - 1;
2156 AstNode
*cond
= new AstNode(AST_COND
, mkconst_int(start_bit
, true));
2157 AstNode
*lvalue
= children
[0]->clone();
2158 lvalue
->delete_children();
2159 lvalue
->children
.push_back(new AstNode(AST_RANGE
,
2160 mkconst_int(end_bit
, true), mkconst_int(start_bit
, true)));
2161 cond
->children
.push_back(new AstNode(AST_BLOCK
, new AstNode(type
, lvalue
, children
[1]->clone())));
2162 newNode
->children
.push_back(cond
);
2167 // mask and shift operations, disabled for now
2169 AstNode
*wire_mask
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(source_width
-1, true), mkconst_int(0, true)));
2170 wire_mask
->str
= stringf("$bitselwrite$mask$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
2171 wire_mask
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
2172 wire_mask
->is_logic
= true;
2173 while (wire_mask
->simplify(true, false, false, 1, -1, false, false)) { }
2174 current_ast_mod
->children
.push_back(wire_mask
);
2176 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(source_width
-1, true), mkconst_int(0, true)));
2177 wire_data
->str
= stringf("$bitselwrite$data$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
2178 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
2179 wire_data
->is_logic
= true;
2180 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
2181 current_ast_mod
->children
.push_back(wire_data
);
2183 did_something
= true;
2184 newNode
= new AstNode(AST_BLOCK
);
2186 AstNode
*lvalue
= children
[0]->clone();
2187 lvalue
->delete_children();
2189 AstNode
*ref_mask
= new AstNode(AST_IDENTIFIER
);
2190 ref_mask
->str
= wire_mask
->str
;
2191 ref_mask
->id2ast
= wire_mask
;
2192 ref_mask
->was_checked
= true;
2194 AstNode
*ref_data
= new AstNode(AST_IDENTIFIER
);
2195 ref_data
->str
= wire_data
->str
;
2196 ref_data
->id2ast
= wire_data
;
2197 ref_data
->was_checked
= true;
2199 AstNode
*old_data
= lvalue
->clone();
2200 if (type
== AST_ASSIGN_LE
)
2201 old_data
->lookahead
= true;
2203 AstNode
*shamt
= shift_expr
;
2205 int shamt_width_hint
= 0;
2206 bool shamt_sign_hint
= true;
2207 shamt
->detectSignWidth(shamt_width_hint
, shamt_sign_hint
);
2209 int start_bit
= children
[0]->id2ast
->range_right
;
2210 bool use_shift
= shamt_sign_hint
;
2212 if (start_bit
!= 0) {
2213 shamt
= new AstNode(AST_SUB
, shamt
, mkconst_int(start_bit
, true));
2219 t
= mkconst_bits(std::vector
<RTLIL::State
>(result_width
, State::S1
), false);
2221 t
= new AstNode(AST_SHIFT
, t
, new AstNode(AST_NEG
, shamt
->clone()));
2223 t
= new AstNode(AST_SHIFT_LEFT
, t
, shamt
->clone());
2224 t
= new AstNode(AST_ASSIGN_EQ
, ref_mask
->clone(), t
);
2225 newNode
->children
.push_back(t
);
2227 t
= new AstNode(AST_BIT_AND
, mkconst_bits(std::vector
<RTLIL::State
>(result_width
, State::S1
), false), children
[1]->clone());
2229 t
= new AstNode(AST_SHIFT
, t
, new AstNode(AST_NEG
, shamt
));
2231 t
= new AstNode(AST_SHIFT_LEFT
, t
, shamt
);
2232 t
= new AstNode(AST_ASSIGN_EQ
, ref_data
->clone(), t
);
2233 newNode
->children
.push_back(t
);
2235 t
= new AstNode(AST_BIT_AND
, old_data
, new AstNode(AST_BIT_NOT
, ref_mask
));
2236 t
= new AstNode(AST_BIT_OR
, t
, ref_data
);
2237 t
= new AstNode(type
, lvalue
, t
);
2238 newNode
->children
.push_back(t
);
2243 skip_dynamic_range_lvalue_expansion
:;
2245 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && current_block
!= NULL
)
2247 std::stringstream sstr
;
2248 sstr
<< "$formal$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
2249 std::string id_check
= sstr
.str() + "_CHECK", id_en
= sstr
.str() + "_EN";
2251 AstNode
*wire_check
= new AstNode(AST_WIRE
);
2252 wire_check
->str
= id_check
;
2253 wire_check
->was_checked
= true;
2254 current_ast_mod
->children
.push_back(wire_check
);
2255 current_scope
[wire_check
->str
] = wire_check
;
2256 while (wire_check
->simplify(true, false, false, 1, -1, false, false)) { }
2258 AstNode
*wire_en
= new AstNode(AST_WIRE
);
2259 wire_en
->str
= id_en
;
2260 wire_en
->was_checked
= true;
2261 current_ast_mod
->children
.push_back(wire_en
);
2262 if (current_always_clocked
) {
2263 current_ast_mod
->children
.push_back(new AstNode(AST_INITIAL
, new AstNode(AST_BLOCK
, new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), AstNode::mkconst_int(0, false, 1)))));
2264 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->str
= id_en
;
2265 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->was_checked
= true;
2267 current_scope
[wire_en
->str
] = wire_en
;
2268 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
2270 AstNode
*check_defval
;
2271 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
2272 check_defval
= new AstNode(AST_REDUCE_BOOL
, children
[0]->clone());
2274 std::vector
<RTLIL::State
> x_bit
;
2275 x_bit
.push_back(RTLIL::State::Sx
);
2276 check_defval
= mkconst_bits(x_bit
, false);
2279 AstNode
*assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), check_defval
);
2280 assign_check
->children
[0]->str
= id_check
;
2281 assign_check
->children
[0]->was_checked
= true;
2283 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, 1));
2284 assign_en
->children
[0]->str
= id_en
;
2285 assign_en
->children
[0]->was_checked
= true;
2287 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
2288 default_signals
->children
.push_back(assign_check
);
2289 default_signals
->children
.push_back(assign_en
);
2290 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
2292 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
2293 assign_check
= nullptr;
2295 assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_REDUCE_BOOL
, children
[0]->clone()));
2296 assign_check
->children
[0]->str
= id_check
;
2297 assign_check
->children
[0]->was_checked
= true;
2300 if (current_always
== nullptr || current_always
->type
!= AST_INITIAL
) {
2301 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(1, false, 1));
2303 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_FCALL
));
2304 assign_en
->children
[1]->str
= "\\$initstate";
2306 assign_en
->children
[0]->str
= id_en
;
2307 assign_en
->children
[0]->was_checked
= true;
2309 newNode
= new AstNode(AST_BLOCK
);
2310 if (assign_check
!= nullptr)
2311 newNode
->children
.push_back(assign_check
);
2312 newNode
->children
.push_back(assign_en
);
2314 AstNode
*assertnode
= new AstNode(type
);
2315 assertnode
->location
= location
;
2316 assertnode
->str
= str
;
2317 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
2318 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
2319 assertnode
->children
[0]->str
= id_check
;
2320 assertnode
->children
[1]->str
= id_en
;
2321 assertnode
->attributes
.swap(attributes
);
2322 current_ast_mod
->children
.push_back(assertnode
);
2327 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && children
.size() == 1)
2329 children
.push_back(mkconst_int(1, false, 1));
2330 did_something
= true;
2333 // found right-hand side identifier for memory -> replace with memory read port
2334 if (stage
> 1 && type
== AST_IDENTIFIER
&& id2ast
!= NULL
&& id2ast
->type
== AST_MEMORY
&& !in_lvalue
&&
2335 children
.size() == 1 && children
[0]->type
== AST_RANGE
&& children
[0]->children
.size() == 1) {
2336 newNode
= new AstNode(AST_MEMRD
, children
[0]->children
[0]->clone());
2338 newNode
->id2ast
= id2ast
;
2342 // assignment with nontrivial member in left-hand concat expression -> split assignment
2343 if ((type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_CONCAT
&& width_hint
> 0)
2345 bool found_nontrivial_member
= false;
2347 for (auto child
: children
[0]->children
) {
2348 if (child
->type
== AST_IDENTIFIER
&& child
->id2ast
!= NULL
&& child
->id2ast
->type
== AST_MEMORY
)
2349 found_nontrivial_member
= true;
2352 if (found_nontrivial_member
)
2354 newNode
= new AstNode(AST_BLOCK
);
2356 AstNode
*wire_tmp
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
2357 wire_tmp
->str
= stringf("$splitcmplxassign$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
2358 current_ast_mod
->children
.push_back(wire_tmp
);
2359 current_scope
[wire_tmp
->str
] = wire_tmp
;
2360 wire_tmp
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
2361 while (wire_tmp
->simplify(true, false, false, 1, -1, false, false)) { }
2362 wire_tmp
->is_logic
= true;
2364 AstNode
*wire_tmp_id
= new AstNode(AST_IDENTIFIER
);
2365 wire_tmp_id
->str
= wire_tmp
->str
;
2367 newNode
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, wire_tmp_id
, children
[1]->clone()));
2368 newNode
->children
.back()->was_checked
= true;
2371 for (auto child
: children
[0]->children
)
2373 int child_width_hint
= -1;
2374 bool child_sign_hint
= true;
2375 child
->detectSignWidth(child_width_hint
, child_sign_hint
);
2377 AstNode
*rhs
= wire_tmp_id
->clone();
2378 rhs
->children
.push_back(new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+child_width_hint
-1, true), AstNode::mkconst_int(cursor
, true)));
2379 newNode
->children
.push_back(new AstNode(type
, child
->clone(), rhs
));
2381 cursor
+= child_width_hint
;
2388 // assignment with memory in left-hand side expression -> replace with memory write port
2389 if (stage
> 1 && (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_IDENTIFIER
&&
2390 children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
&& children
[0]->id2ast
->children
.size() >= 2 &&
2391 children
[0]->id2ast
->children
[0]->range_valid
&& children
[0]->id2ast
->children
[1]->range_valid
&&
2392 (children
[0]->children
.size() == 1 || children
[0]->children
.size() == 2) && children
[0]->children
[0]->type
== AST_RANGE
)
2394 std::stringstream sstr
;
2395 sstr
<< "$memwr$" << children
[0]->str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
2396 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA", id_en
= sstr
.str() + "_EN";
2398 int mem_width
, mem_size
, addr_bits
;
2399 bool mem_signed
= children
[0]->id2ast
->is_signed
;
2400 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
2402 newNode
= new AstNode(AST_BLOCK
);
2403 AstNode
*defNode
= new AstNode(AST_BLOCK
);
2405 int data_range_left
= children
[0]->id2ast
->children
[0]->range_left
;
2406 int data_range_right
= children
[0]->id2ast
->children
[0]->range_right
;
2407 int mem_data_range_offset
= std::min(data_range_left
, data_range_right
);
2409 int addr_width_hint
= -1;
2410 bool addr_sign_hint
= true;
2411 children
[0]->children
[0]->children
[0]->detectSignWidthWorker(addr_width_hint
, addr_sign_hint
);
2412 addr_bits
= std::max(addr_bits
, addr_width_hint
);
2414 std::vector
<RTLIL::State
> x_bits_addr
, x_bits_data
, set_bits_en
;
2415 for (int i
= 0; i
< addr_bits
; i
++)
2416 x_bits_addr
.push_back(RTLIL::State::Sx
);
2417 for (int i
= 0; i
< mem_width
; i
++)
2418 x_bits_data
.push_back(RTLIL::State::Sx
);
2419 for (int i
= 0; i
< mem_width
; i
++)
2420 set_bits_en
.push_back(RTLIL::State::S1
);
2422 AstNode
*node_addr
= nullptr;
2423 if (children
[0]->children
[0]->children
[0]->isConst()) {
2424 node_addr
= children
[0]->children
[0]->children
[0]->clone();
2426 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
2427 wire_addr
->str
= id_addr
;
2428 wire_addr
->was_checked
= true;
2429 current_ast_mod
->children
.push_back(wire_addr
);
2430 current_scope
[wire_addr
->str
] = wire_addr
;
2431 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
2433 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_addr
, false));
2434 assign_addr
->children
[0]->str
= id_addr
;
2435 assign_addr
->children
[0]->was_checked
= true;
2436 defNode
->children
.push_back(assign_addr
);
2438 assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
2439 assign_addr
->children
[0]->str
= id_addr
;
2440 assign_addr
->children
[0]->was_checked
= true;
2441 newNode
->children
.push_back(assign_addr
);
2443 node_addr
= new AstNode(AST_IDENTIFIER
);
2444 node_addr
->str
= id_addr
;
2447 AstNode
*node_data
= nullptr;
2448 if (children
[0]->children
.size() == 1 && children
[1]->isConst()) {
2449 node_data
= children
[1]->clone();
2451 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
2452 wire_data
->str
= id_data
;
2453 wire_data
->was_checked
= true;
2454 wire_data
->is_signed
= mem_signed
;
2455 current_ast_mod
->children
.push_back(wire_data
);
2456 current_scope
[wire_data
->str
] = wire_data
;
2457 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
2459 AstNode
*assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_data
, false));
2460 assign_data
->children
[0]->str
= id_data
;
2461 assign_data
->children
[0]->was_checked
= true;
2462 defNode
->children
.push_back(assign_data
);
2464 node_data
= new AstNode(AST_IDENTIFIER
);
2465 node_data
->str
= id_data
;
2468 AstNode
*node_en
= nullptr;
2469 if (current_always
->type
== AST_INITIAL
) {
2470 node_en
= AstNode::mkconst_int(1, false);
2472 AstNode
*wire_en
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
2473 wire_en
->str
= id_en
;
2474 wire_en
->was_checked
= true;
2475 current_ast_mod
->children
.push_back(wire_en
);
2476 current_scope
[wire_en
->str
] = wire_en
;
2477 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
2479 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, mem_width
));
2480 assign_en
->children
[0]->str
= id_en
;
2481 assign_en
->children
[0]->was_checked
= true;
2482 defNode
->children
.push_back(assign_en
);
2484 node_en
= new AstNode(AST_IDENTIFIER
);
2485 node_en
->str
= id_en
;
2488 if (!defNode
->children
.empty())
2489 current_top_block
->children
.insert(current_top_block
->children
.begin(), defNode
);
2493 AstNode
*assign_data
= nullptr;
2494 AstNode
*assign_en
= nullptr;
2495 if (children
[0]->children
.size() == 2)
2497 if (children
[0]->children
[1]->range_valid
)
2499 int offset
= children
[0]->children
[1]->range_right
;
2500 int width
= children
[0]->children
[1]->range_left
- offset
+ 1;
2501 offset
-= mem_data_range_offset
;
2503 std::vector
<RTLIL::State
> padding_x(offset
, RTLIL::State::Sx
);
2505 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
2506 new AstNode(AST_CONCAT
, mkconst_bits(padding_x
, false), children
[1]->clone()));
2507 assign_data
->children
[0]->str
= id_data
;
2508 assign_data
->children
[0]->was_checked
= true;
2510 if (current_always
->type
!= AST_INITIAL
) {
2511 for (int i
= 0; i
< mem_width
; i
++)
2512 set_bits_en
[i
] = offset
<= i
&& i
< offset
+width
? RTLIL::State::S1
: RTLIL::State::S0
;
2513 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
2514 assign_en
->children
[0]->str
= id_en
;
2515 assign_en
->children
[0]->was_checked
= true;
2520 AstNode
*the_range
= children
[0]->children
[1];
2521 AstNode
*left_at_zero_ast
= the_range
->children
[0]->clone();
2522 AstNode
*right_at_zero_ast
= the_range
->children
.size() >= 2 ? the_range
->children
[1]->clone() : left_at_zero_ast
->clone();
2523 AstNode
*offset_ast
= right_at_zero_ast
->clone();
2525 if (mem_data_range_offset
)
2526 offset_ast
= new AstNode(AST_SUB
, offset_ast
, mkconst_int(mem_data_range_offset
, true));
2528 while (left_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
2529 while (right_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
2530 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
2531 log_file_error(filename
, location
.first_line
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
2532 int width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
2534 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
2535 new AstNode(AST_SHIFT_LEFT
, children
[1]->clone(), offset_ast
->clone()));
2536 assign_data
->children
[0]->str
= id_data
;
2537 assign_data
->children
[0]->was_checked
= true;
2539 if (current_always
->type
!= AST_INITIAL
) {
2540 for (int i
= 0; i
< mem_width
; i
++)
2541 set_bits_en
[i
] = i
< width
? RTLIL::State::S1
: RTLIL::State::S0
;
2542 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
2543 new AstNode(AST_SHIFT_LEFT
, mkconst_bits(set_bits_en
, false), offset_ast
->clone()));
2544 assign_en
->children
[0]->str
= id_en
;
2545 assign_en
->children
[0]->was_checked
= true;
2548 delete left_at_zero_ast
;
2549 delete right_at_zero_ast
;
2555 if (!(children
[0]->children
.size() == 1 && children
[1]->isConst())) {
2556 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[1]->clone());
2557 assign_data
->children
[0]->str
= id_data
;
2558 assign_data
->children
[0]->was_checked
= true;
2561 if (current_always
->type
!= AST_INITIAL
) {
2562 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
2563 assign_en
->children
[0]->str
= id_en
;
2564 assign_en
->children
[0]->was_checked
= true;
2568 newNode
->children
.push_back(assign_data
);
2570 newNode
->children
.push_back(assign_en
);
2572 AstNode
*wrnode
= new AstNode(current_always
->type
== AST_INITIAL
? AST_MEMINIT
: AST_MEMWR
, node_addr
, node_data
, node_en
);
2573 wrnode
->str
= children
[0]->str
;
2574 wrnode
->id2ast
= children
[0]->id2ast
;
2575 current_ast_mod
->children
.push_back(wrnode
);
2577 if (newNode
->children
.empty()) {
2579 newNode
= new AstNode();
2584 // replace function and task calls with the code from the function or task
2585 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && !str
.empty())
2587 if (type
== AST_FCALL
)
2589 if (str
== "\\$initstate")
2591 int myidx
= autoidx
++;
2593 AstNode
*wire
= new AstNode(AST_WIRE
);
2594 wire
->str
= stringf("$initstate$%d_wire", myidx
);
2595 current_ast_mod
->children
.push_back(wire
);
2596 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2598 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
), new AstNode(AST_ARGUMENT
, new AstNode(AST_IDENTIFIER
)));
2599 cell
->str
= stringf("$initstate$%d", myidx
);
2600 cell
->children
[0]->str
= "$initstate";
2601 cell
->children
[1]->str
= "\\Y";
2602 cell
->children
[1]->children
[0]->str
= wire
->str
;
2603 cell
->children
[1]->children
[0]->id2ast
= wire
;
2604 current_ast_mod
->children
.push_back(cell
);
2605 while (cell
->simplify(true, false, false, 1, -1, false, false)) { }
2607 newNode
= new AstNode(AST_IDENTIFIER
);
2608 newNode
->str
= wire
->str
;
2609 newNode
->id2ast
= wire
;
2613 if (str
== "\\$past")
2616 goto replace_fcall_later
;
2620 if (GetSize(children
) != 1 && GetSize(children
) != 2)
2621 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1 or 2.\n",
2622 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2624 if (!current_always_clocked
)
2625 log_file_error(filename
, location
.first_line
, "System function %s is only allowed in clocked blocks.\n",
2626 RTLIL::unescape_id(str
).c_str());
2628 if (GetSize(children
) == 2)
2630 AstNode
*buf
= children
[1]->clone();
2631 while (buf
->simplify(true, false, false, stage
, -1, false, false)) { }
2632 if (buf
->type
!= AST_CONSTANT
)
2633 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
2635 num_steps
= buf
->asInt(true);
2639 AstNode
*block
= nullptr;
2641 for (auto child
: current_always
->children
)
2642 if (child
->type
== AST_BLOCK
)
2645 log_assert(block
!= nullptr);
2647 if (num_steps
== 0) {
2648 newNode
= children
[0]->clone();
2652 int myidx
= autoidx
++;
2653 AstNode
*outreg
= nullptr;
2655 for (int i
= 0; i
< num_steps
; i
++)
2657 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
2658 mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
2660 reg
->str
= stringf("$past$%s:%d$%d$%d", filename
.c_str(), location
.first_line
, myidx
, i
);
2663 current_ast_mod
->children
.push_back(reg
);
2665 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
2667 AstNode
*regid
= new AstNode(AST_IDENTIFIER
);
2668 regid
->str
= reg
->str
;
2669 regid
->id2ast
= reg
;
2670 regid
->was_checked
= true;
2672 AstNode
*rhs
= nullptr;
2674 if (outreg
== nullptr) {
2675 rhs
= children
.at(0)->clone();
2677 rhs
= new AstNode(AST_IDENTIFIER
);
2678 rhs
->str
= outreg
->str
;
2679 rhs
->id2ast
= outreg
;
2682 block
->children
.push_back(new AstNode(AST_ASSIGN_LE
, regid
, rhs
));
2686 newNode
= new AstNode(AST_IDENTIFIER
);
2687 newNode
->str
= outreg
->str
;
2688 newNode
->id2ast
= outreg
;
2692 if (str
== "\\$stable" || str
== "\\$rose" || str
== "\\$fell" || str
== "\\$changed")
2694 if (GetSize(children
) != 1)
2695 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2696 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2698 if (!current_always_clocked
)
2699 log_file_error(filename
, location
.first_line
, "System function %s is only allowed in clocked blocks.\n",
2700 RTLIL::unescape_id(str
).c_str());
2702 AstNode
*present
= children
.at(0)->clone();
2703 AstNode
*past
= clone();
2704 past
->str
= "\\$past";
2706 if (str
== "\\$stable")
2707 newNode
= new AstNode(AST_EQ
, past
, present
);
2709 else if (str
== "\\$changed")
2710 newNode
= new AstNode(AST_NE
, past
, present
);
2712 else if (str
== "\\$rose")
2713 newNode
= new AstNode(AST_LOGIC_AND
,
2714 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false))),
2715 new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false)));
2717 else if (str
== "\\$fell")
2718 newNode
= new AstNode(AST_LOGIC_AND
,
2719 new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false)),
2720 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false))));
2728 // $anyconst and $anyseq are mapped in AstNode::genRTLIL()
2729 if (str
== "\\$anyconst" || str
== "\\$anyseq" || str
== "\\$allconst" || str
== "\\$allseq") {
2730 recursion_counter
--;
2734 if (str
== "\\$clog2")
2736 if (children
.size() != 1)
2737 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2738 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2740 AstNode
*buf
= children
[0]->clone();
2741 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2742 if (buf
->type
!= AST_CONSTANT
)
2743 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
2745 RTLIL::Const arg_value
= buf
->bitsAsConst();
2746 if (arg_value
.as_bool())
2747 arg_value
= const_sub(arg_value
, 1, false, false, GetSize(arg_value
));
2750 uint32_t result
= 0;
2751 for (size_t i
= 0; i
< arg_value
.bits
.size(); i
++)
2752 if (arg_value
.bits
.at(i
) == RTLIL::State::S1
)
2755 newNode
= mkconst_int(result
, true);
2759 if (str
== "\\$size" || str
== "\\$bits")
2761 if (str
== "\\$bits" && children
.size() != 1)
2762 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2763 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2765 if (str
== "\\$size" && children
.size() != 1 && children
.size() != 2)
2766 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1 or 2.\n",
2767 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2770 if (str
== "\\$size" && children
.size() == 2) {
2771 AstNode
*buf
= children
[1]->clone();
2772 // Evaluate constant expression
2773 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2774 dim
= buf
->asInt(false);
2777 AstNode
*buf
= children
[0]->clone();
2779 AstNode
*id_ast
= NULL
;
2782 //while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2783 buf
->detectSignWidth(width_hint
, sign_hint
);
2785 if (buf
->type
== AST_IDENTIFIER
) {
2786 id_ast
= buf
->id2ast
;
2787 if (id_ast
== NULL
&& current_scope
.count(buf
->str
))
2788 id_ast
= current_scope
.at(buf
->str
);
2790 log_file_error(filename
, location
.first_line
, "Failed to resolve identifier %s for width detection!\n", buf
->str
.c_str());
2791 if (id_ast
->type
== AST_MEMORY
) {
2792 // We got here only if the argument is a memory
2793 // Otherwise $size() and $bits() return the expression width
2794 AstNode
*mem_range
= id_ast
->children
[1];
2795 if (str
== "\\$bits") {
2796 if (mem_range
->type
== AST_RANGE
) {
2797 if (!mem_range
->range_valid
)
2798 log_file_error(filename
, location
.first_line
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2799 mem_depth
= mem_range
->range_left
- mem_range
->range_right
+ 1;
2801 log_file_error(filename
, location
.first_line
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2804 if (mem_range
->type
== AST_RANGE
) {
2805 if (!mem_range
->range_valid
)
2806 log_file_error(filename
, location
.first_line
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2808 if (id_ast
->multirange_dimensions
.empty())
2811 dims
= GetSize(id_ast
->multirange_dimensions
)/2;
2813 width_hint
= (dims
> 1) ? id_ast
->multirange_dimensions
[1] : (mem_range
->range_left
- mem_range
->range_right
+ 1);
2814 else if (dim
<= dims
) {
2815 width_hint
= id_ast
->multirange_dimensions
[2*dim
-1];
2816 } else if ((dim
> dims
+1) || (dim
< 0))
2817 log_file_error(filename
, location
.first_line
, "Dimension %d out of range in `%s', as it only has dimensions 1..%d!\n", dim
, buf
->str
.c_str(), dims
+1);
2819 log_file_error(filename
, location
.first_line
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2825 newNode
= mkconst_int(width_hint
* mem_depth
, false);
2829 if (str
== "\\$ln" || str
== "\\$log10" || str
== "\\$exp" || str
== "\\$sqrt" || str
== "\\$pow" ||
2830 str
== "\\$floor" || str
== "\\$ceil" || str
== "\\$sin" || str
== "\\$cos" || str
== "\\$tan" ||
2831 str
== "\\$asin" || str
== "\\$acos" || str
== "\\$atan" || str
== "\\$atan2" || str
== "\\$hypot" ||
2832 str
== "\\$sinh" || str
== "\\$cosh" || str
== "\\$tanh" || str
== "\\$asinh" || str
== "\\$acosh" || str
== "\\$atanh" ||
2833 str
== "\\$rtoi" || str
== "\\$itor")
2835 bool func_with_two_arguments
= str
== "\\$pow" || str
== "\\$atan2" || str
== "\\$hypot";
2836 double x
= 0, y
= 0;
2838 if (func_with_two_arguments
) {
2839 if (children
.size() != 2)
2840 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 2.\n",
2841 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2843 if (children
.size() != 1)
2844 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2845 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2848 if (children
.size() >= 1) {
2849 while (children
[0]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2850 if (!children
[0]->isConst())
2851 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant argument.\n",
2852 RTLIL::unescape_id(str
).c_str());
2853 int child_width_hint
= width_hint
;
2854 bool child_sign_hint
= sign_hint
;
2855 children
[0]->detectSignWidth(child_width_hint
, child_sign_hint
);
2856 x
= children
[0]->asReal(child_sign_hint
);
2859 if (children
.size() >= 2) {
2860 while (children
[1]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2861 if (!children
[1]->isConst())
2862 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant argument.\n",
2863 RTLIL::unescape_id(str
).c_str());
2864 int child_width_hint
= width_hint
;
2865 bool child_sign_hint
= sign_hint
;
2866 children
[1]->detectSignWidth(child_width_hint
, child_sign_hint
);
2867 y
= children
[1]->asReal(child_sign_hint
);
2870 if (str
== "\\$rtoi") {
2871 newNode
= AstNode::mkconst_int(x
, true);
2873 newNode
= new AstNode(AST_REALVALUE
);
2874 if (str
== "\\$ln") newNode
->realvalue
= ::log(x
);
2875 else if (str
== "\\$log10") newNode
->realvalue
= ::log10(x
);
2876 else if (str
== "\\$exp") newNode
->realvalue
= ::exp(x
);
2877 else if (str
== "\\$sqrt") newNode
->realvalue
= ::sqrt(x
);
2878 else if (str
== "\\$pow") newNode
->realvalue
= ::pow(x
, y
);
2879 else if (str
== "\\$floor") newNode
->realvalue
= ::floor(x
);
2880 else if (str
== "\\$ceil") newNode
->realvalue
= ::ceil(x
);
2881 else if (str
== "\\$sin") newNode
->realvalue
= ::sin(x
);
2882 else if (str
== "\\$cos") newNode
->realvalue
= ::cos(x
);
2883 else if (str
== "\\$tan") newNode
->realvalue
= ::tan(x
);
2884 else if (str
== "\\$asin") newNode
->realvalue
= ::asin(x
);
2885 else if (str
== "\\$acos") newNode
->realvalue
= ::acos(x
);
2886 else if (str
== "\\$atan") newNode
->realvalue
= ::atan(x
);
2887 else if (str
== "\\$atan2") newNode
->realvalue
= ::atan2(x
, y
);
2888 else if (str
== "\\$hypot") newNode
->realvalue
= ::hypot(x
, y
);
2889 else if (str
== "\\$sinh") newNode
->realvalue
= ::sinh(x
);
2890 else if (str
== "\\$cosh") newNode
->realvalue
= ::cosh(x
);
2891 else if (str
== "\\$tanh") newNode
->realvalue
= ::tanh(x
);
2892 else if (str
== "\\$asinh") newNode
->realvalue
= ::asinh(x
);
2893 else if (str
== "\\$acosh") newNode
->realvalue
= ::acosh(x
);
2894 else if (str
== "\\$atanh") newNode
->realvalue
= ::atanh(x
);
2895 else if (str
== "\\$itor") newNode
->realvalue
= x
;
2901 if (str
== "\\$sformatf") {
2902 AstNode
*node_string
= children
[0];
2903 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2904 if (node_string
->type
!= AST_CONSTANT
)
2905 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
2906 std::string sformat
= node_string
->bitsAsConst().decode_string();
2907 std::string sout
= process_format_str(sformat
, 1, stage
, width_hint
, sign_hint
);
2908 newNode
= AstNode::mkconst_str(sout
);
2912 if (current_scope
.count(str
) != 0 && current_scope
[str
]->type
== AST_DPI_FUNCTION
)
2914 AstNode
*dpi_decl
= current_scope
[str
];
2916 std::string rtype
, fname
;
2917 std::vector
<std::string
> argtypes
;
2918 std::vector
<AstNode
*> args
;
2920 rtype
= RTLIL::unescape_id(dpi_decl
->children
.at(0)->str
);
2921 fname
= RTLIL::unescape_id(dpi_decl
->children
.at(1)->str
);
2923 for (int i
= 2; i
< GetSize(dpi_decl
->children
); i
++)
2925 if (i
-2 >= GetSize(children
))
2926 log_file_error(filename
, location
.first_line
, "Insufficient number of arguments in DPI function call.\n");
2928 argtypes
.push_back(RTLIL::unescape_id(dpi_decl
->children
.at(i
)->str
));
2929 args
.push_back(children
.at(i
-2)->clone());
2930 while (args
.back()->simplify(true, false, false, stage
, -1, false, true)) { }
2932 if (args
.back()->type
!= AST_CONSTANT
&& args
.back()->type
!= AST_REALVALUE
)
2933 log_file_error(filename
, location
.first_line
, "Failed to evaluate DPI function with non-constant argument.\n");
2936 newNode
= dpi_call(rtype
, fname
, argtypes
, args
);
2938 for (auto arg
: args
)
2944 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_FUNCTION
)
2945 log_file_error(filename
, location
.first_line
, "Can't resolve function name `%s'.\n", str
.c_str());
2948 if (type
== AST_TCALL
)
2950 if (str
== "$finish" || str
== "$stop")
2952 if (!current_always
|| current_always
->type
!= AST_INITIAL
)
2953 log_file_error(filename
, location
.first_line
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
2955 log_file_error(filename
, location
.first_line
, "System task `%s' executed.\n", str
.c_str());
2958 if (str
== "\\$readmemh" || str
== "\\$readmemb")
2960 if (GetSize(children
) < 2 || GetSize(children
) > 4)
2961 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 2-4.\n",
2962 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2964 AstNode
*node_filename
= children
[0]->clone();
2965 while (node_filename
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2966 if (node_filename
->type
!= AST_CONSTANT
)
2967 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
2969 AstNode
*node_memory
= children
[1]->clone();
2970 while (node_memory
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2971 if (node_memory
->type
!= AST_IDENTIFIER
|| node_memory
->id2ast
== nullptr || node_memory
->id2ast
->type
!= AST_MEMORY
)
2972 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str
.c_str());
2974 int start_addr
= -1, finish_addr
= -1;
2976 if (GetSize(children
) > 2) {
2977 AstNode
*node_addr
= children
[2]->clone();
2978 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2979 if (node_addr
->type
!= AST_CONSTANT
)
2980 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str
.c_str());
2981 start_addr
= int(node_addr
->asInt(false));
2984 if (GetSize(children
) > 3) {
2985 AstNode
*node_addr
= children
[3]->clone();
2986 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2987 if (node_addr
->type
!= AST_CONSTANT
)
2988 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str
.c_str());
2989 finish_addr
= int(node_addr
->asInt(false));
2992 bool unconditional_init
= false;
2993 if (current_always
->type
== AST_INITIAL
) {
2994 pool
<AstNode
*> queue
;
2995 log_assert(current_always
->children
[0]->type
== AST_BLOCK
);
2996 queue
.insert(current_always
->children
[0]);
2997 while (!unconditional_init
&& !queue
.empty()) {
2998 pool
<AstNode
*> next_queue
;
2999 for (auto n
: queue
)
3000 for (auto c
: n
->children
) {
3002 unconditional_init
= true;
3003 next_queue
.insert(c
);
3005 next_queue
.swap(queue
);
3009 newNode
= readmem(str
== "\\$readmemh", node_filename
->bitsAsConst().decode_string(), node_memory
->id2ast
, start_addr
, finish_addr
, unconditional_init
);
3010 delete node_filename
;
3015 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_TASK
)
3016 log_file_error(filename
, location
.first_line
, "Can't resolve task name `%s'.\n", str
.c_str());
3019 AstNode
*decl
= current_scope
[str
];
3021 std::stringstream sstr
;
3022 sstr
<< "$func$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++) << "$";
3023 std::string prefix
= sstr
.str();
3025 bool recommend_const_eval
= false;
3026 bool require_const_eval
= in_param
? false : has_const_only_constructs(recommend_const_eval
);
3027 if ((in_param
|| recommend_const_eval
|| require_const_eval
) && !decl
->attributes
.count(ID::via_celltype
))
3029 bool all_args_const
= true;
3030 for (auto child
: children
) {
3031 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
3032 if (child
->type
!= AST_CONSTANT
&& child
->type
!= AST_REALVALUE
)
3033 all_args_const
= false;
3036 if (all_args_const
) {
3037 AstNode
*func_workspace
= current_scope
[str
]->clone();
3038 newNode
= func_workspace
->eval_const_function(this);
3039 delete func_workspace
;
3044 log_file_error(filename
, location
.first_line
, "Non-constant function call in constant expression.\n");
3045 if (require_const_eval
)
3046 log_file_error(filename
, location
.first_line
, "Function %s can only be called with constant arguments.\n", str
.c_str());
3049 size_t arg_count
= 0;
3050 std::map
<std::string
, std::string
> replace_rules
;
3051 vector
<AstNode
*> added_mod_children
;
3052 dict
<std::string
, AstNode
*> wire_cache
;
3053 vector
<AstNode
*> new_stmts
;
3054 vector
<AstNode
*> output_assignments
;
3056 if (current_block
== NULL
)
3058 log_assert(type
== AST_FCALL
);
3060 AstNode
*wire
= NULL
;
3061 for (auto child
: decl
->children
)
3062 if (child
->type
== AST_WIRE
&& child
->str
== str
)
3063 wire
= child
->clone();
3064 log_assert(wire
!= NULL
);
3066 wire
->str
= prefix
+ str
;
3068 wire
->is_input
= false;
3069 wire
->is_output
= false;
3071 current_ast_mod
->children
.push_back(wire
);
3072 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
3074 AstNode
*lvalue
= new AstNode(AST_IDENTIFIER
);
3075 lvalue
->str
= wire
->str
;
3077 AstNode
*always
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
,
3078 new AstNode(AST_ASSIGN_EQ
, lvalue
, clone())));
3079 always
->children
[0]->children
[0]->was_checked
= true;
3081 current_ast_mod
->children
.push_back(always
);
3083 goto replace_fcall_with_id
;
3086 if (decl
->attributes
.count(ID::via_celltype
))
3088 std::string celltype
= decl
->attributes
.at(ID::via_celltype
)->asAttrConst().decode_string();
3089 std::string outport
= str
;
3091 if (celltype
.find(' ') != std::string::npos
) {
3092 int pos
= celltype
.find(' ');
3093 outport
= RTLIL::escape_id(celltype
.substr(pos
+1));
3094 celltype
= RTLIL::escape_id(celltype
.substr(0, pos
));
3096 celltype
= RTLIL::escape_id(celltype
);
3098 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
));
3099 cell
->str
= prefix
.substr(0, GetSize(prefix
)-1);
3100 cell
->children
[0]->str
= celltype
;
3102 for (auto attr
: decl
->attributes
)
3103 if (attr
.first
.str().rfind("\\via_celltype_defparam_", 0) == 0)
3105 AstNode
*cell_arg
= new AstNode(AST_PARASET
, attr
.second
->clone());
3106 cell_arg
->str
= RTLIL::escape_id(attr
.first
.substr(strlen("\\via_celltype_defparam_")));
3107 cell
->children
.push_back(cell_arg
);
3110 for (auto child
: decl
->children
)
3111 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
|| (type
== AST_FCALL
&& child
->str
== str
)))
3113 AstNode
*wire
= child
->clone();
3114 wire
->str
= prefix
+ wire
->str
;
3116 wire
->is_input
= false;
3117 wire
->is_output
= false;
3118 current_ast_mod
->children
.push_back(wire
);
3119 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
3121 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
3122 wire_id
->str
= wire
->str
;
3124 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
3126 AstNode
*arg
= children
[arg_count
++]->clone();
3127 AstNode
*assign
= child
->is_input
?
3128 new AstNode(AST_ASSIGN_EQ
, wire_id
->clone(), arg
) :
3129 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
->clone());
3130 assign
->children
[0]->was_checked
= true;
3132 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
3133 if (*it
!= current_block_child
)
3135 current_block
->children
.insert(it
, assign
);
3140 AstNode
*cell_arg
= new AstNode(AST_ARGUMENT
, wire_id
);
3141 cell_arg
->str
= child
->str
== str
? outport
: child
->str
;
3142 cell
->children
.push_back(cell_arg
);
3145 current_ast_mod
->children
.push_back(cell
);
3146 goto replace_fcall_with_id
;
3149 for (auto child
: decl
->children
)
3150 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
|| child
->type
== AST_ENUM_ITEM
)
3152 AstNode
*wire
= nullptr;
3154 if (wire_cache
.count(child
->str
))
3156 wire
= wire_cache
.at(child
->str
);
3157 if (wire
->children
.empty()) {
3158 for (auto c
: child
->children
)
3159 wire
->children
.push_back(c
->clone());
3160 } else if (!child
->children
.empty()) {
3161 while (child
->simplify(true, false, false, stage
, -1, false, false)) { }
3162 if (GetSize(child
->children
) == GetSize(wire
->children
)) {
3163 for (int i
= 0; i
< GetSize(child
->children
); i
++)
3164 if (*child
->children
.at(i
) != *wire
->children
.at(i
))
3165 goto tcall_incompatible_wires
;
3167 tcall_incompatible_wires
:
3168 log_file_error(filename
, location
.first_line
, "Incompatible re-declaration of wire %s.\n", child
->str
.c_str());
3174 wire
= child
->clone();
3175 wire
->str
= prefix
+ wire
->str
;
3177 wire
->is_input
= false;
3178 wire
->is_output
= false;
3179 wire
->is_reg
= true;
3180 wire
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
3181 if (child
->type
== AST_ENUM_ITEM
)
3182 wire
->attributes
[ID::enum_base_type
] = child
->attributes
[ID::enum_base_type
];
3184 wire_cache
[child
->str
] = wire
;
3186 current_ast_mod
->children
.push_back(wire
);
3187 added_mod_children
.push_back(wire
);
3190 if (child
->type
== AST_WIRE
)
3191 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
3193 replace_rules
[child
->str
] = wire
->str
;
3194 current_scope
[wire
->str
] = wire
;
3196 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
3198 AstNode
*arg
= children
[arg_count
++]->clone();
3199 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
3200 wire_id
->str
= wire
->str
;
3201 AstNode
*assign
= child
->is_input
?
3202 new AstNode(AST_ASSIGN_EQ
, wire_id
, arg
) :
3203 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
);
3204 assign
->children
[0]->was_checked
= true;
3205 if (child
->is_input
)
3206 new_stmts
.push_back(assign
);
3208 output_assignments
.push_back(assign
);
3212 for (auto child
: added_mod_children
) {
3213 child
->replace_ids(prefix
, replace_rules
);
3214 while (child
->simplify(true, false, false, 1, -1, false, false)) { }
3217 for (auto child
: decl
->children
)
3218 if (child
->type
!= AST_WIRE
&& child
->type
!= AST_MEMORY
&& child
->type
!= AST_PARAMETER
&& child
->type
!= AST_LOCALPARAM
)
3220 AstNode
*stmt
= child
->clone();
3221 stmt
->replace_ids(prefix
, replace_rules
);
3222 new_stmts
.push_back(stmt
);
3225 new_stmts
.insert(new_stmts
.end(), output_assignments
.begin(), output_assignments
.end());
3227 for (auto it
= current_block
->children
.begin(); ; it
++) {
3228 log_assert(it
!= current_block
->children
.end());
3229 if (*it
== current_block_child
) {
3230 current_block
->children
.insert(it
, new_stmts
.begin(), new_stmts
.end());
3235 replace_fcall_with_id
:
3236 if (type
== AST_FCALL
) {
3238 type
= AST_IDENTIFIER
;
3241 if (type
== AST_TCALL
)
3243 did_something
= true;
3246 replace_fcall_later
:;
3248 // perform const folding when activated
3252 std::vector
<RTLIL::State
> tmp_bits
;
3253 RTLIL::Const (*const_func
)(const RTLIL::Const
&, const RTLIL::Const
&, bool, bool, int);
3254 RTLIL::Const dummy_arg
;
3258 case AST_IDENTIFIER
:
3259 if (current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
|| current_scope
[str
]->type
== AST_ENUM_ITEM
)) {
3260 if (current_scope
[str
]->children
[0]->type
== AST_CONSTANT
) {
3261 if (children
.size() != 0 && children
[0]->type
== AST_RANGE
&& children
[0]->range_valid
) {
3262 std::vector
<RTLIL::State
> data
;
3263 bool param_upto
= current_scope
[str
]->range_valid
&& current_scope
[str
]->range_swapped
;
3264 int param_offset
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_right
: 0;
3265 int param_width
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_left
- current_scope
[str
]->range_right
+ 1 :
3266 GetSize(current_scope
[str
]->children
[0]->bits
);
3267 int tmp_range_left
= children
[0]->range_left
, tmp_range_right
= children
[0]->range_right
;
3269 tmp_range_left
= (param_width
+ 2*param_offset
) - children
[0]->range_right
- 1;
3270 tmp_range_right
= (param_width
+ 2*param_offset
) - children
[0]->range_left
- 1;
3272 for (int i
= tmp_range_right
; i
<= tmp_range_left
; i
++) {
3273 int index
= i
- param_offset
;
3274 if (0 <= index
&& index
< param_width
)
3275 data
.push_back(current_scope
[str
]->children
[0]->bits
[index
]);
3277 data
.push_back(RTLIL::State::Sx
);
3279 newNode
= mkconst_bits(data
, false);
3281 if (children
.size() == 0)
3282 newNode
= current_scope
[str
]->children
[0]->clone();
3284 if (current_scope
[str
]->children
[0]->isConst())
3285 newNode
= current_scope
[str
]->children
[0]->clone();
3287 else if (at_zero
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_WIRE
|| current_scope
[str
]->type
== AST_AUTOWIRE
)) {
3288 newNode
= mkconst_int(0, sign_hint
, width_hint
);
3292 if (children
[0]->type
== AST_CONSTANT
) {
3293 RTLIL::Const y
= RTLIL::const_not(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
3294 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3298 case AST_TO_UNSIGNED
:
3299 if (children
[0]->type
== AST_CONSTANT
) {
3300 RTLIL::Const y
= children
[0]->bitsAsConst(width_hint
, sign_hint
);
3301 newNode
= mkconst_bits(y
.bits
, type
== AST_TO_SIGNED
);
3304 if (0) { case AST_BIT_AND
: const_func
= RTLIL::const_and
; }
3305 if (0) { case AST_BIT_OR
: const_func
= RTLIL::const_or
; }
3306 if (0) { case AST_BIT_XOR
: const_func
= RTLIL::const_xor
; }
3307 if (0) { case AST_BIT_XNOR
: const_func
= RTLIL::const_xnor
; }
3308 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3309 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3310 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
3311 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3314 if (0) { case AST_REDUCE_AND
: const_func
= RTLIL::const_reduce_and
; }
3315 if (0) { case AST_REDUCE_OR
: const_func
= RTLIL::const_reduce_or
; }
3316 if (0) { case AST_REDUCE_XOR
: const_func
= RTLIL::const_reduce_xor
; }
3317 if (0) { case AST_REDUCE_XNOR
: const_func
= RTLIL::const_reduce_xnor
; }
3318 if (0) { case AST_REDUCE_BOOL
: const_func
= RTLIL::const_reduce_bool
; }
3319 if (children
[0]->type
== AST_CONSTANT
) {
3320 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), dummy_arg
, false, false, -1);
3321 newNode
= mkconst_bits(y
.bits
, false);
3325 if (children
[0]->type
== AST_CONSTANT
) {
3326 RTLIL::Const y
= RTLIL::const_logic_not(RTLIL::Const(children
[0]->bits
), dummy_arg
, children
[0]->is_signed
, false, -1);
3327 newNode
= mkconst_bits(y
.bits
, false);
3329 if (children
[0]->isConst()) {
3330 newNode
= mkconst_int(children
[0]->asReal(sign_hint
) == 0, false, 1);
3333 if (0) { case AST_LOGIC_AND
: const_func
= RTLIL::const_logic_and
; }
3334 if (0) { case AST_LOGIC_OR
: const_func
= RTLIL::const_logic_or
; }
3335 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3336 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), RTLIL::Const(children
[1]->bits
),
3337 children
[0]->is_signed
, children
[1]->is_signed
, -1);
3338 newNode
= mkconst_bits(y
.bits
, false);
3340 if (children
[0]->isConst() && children
[1]->isConst()) {
3341 if (type
== AST_LOGIC_AND
)
3342 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) && (children
[1]->asReal(sign_hint
) != 0), false, 1);
3344 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) || (children
[1]->asReal(sign_hint
) != 0), false, 1);
3347 if (0) { case AST_SHIFT_LEFT
: const_func
= RTLIL::const_shl
; }
3348 if (0) { case AST_SHIFT_RIGHT
: const_func
= RTLIL::const_shr
; }
3349 if (0) { case AST_SHIFT_SLEFT
: const_func
= RTLIL::const_sshl
; }
3350 if (0) { case AST_SHIFT_SRIGHT
: const_func
= RTLIL::const_sshr
; }
3351 if (0) { case AST_POW
: const_func
= RTLIL::const_pow
; }
3352 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3353 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3354 RTLIL::Const(children
[1]->bits
), sign_hint
, type
== AST_POW
? children
[1]->is_signed
: false, width_hint
);
3355 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3357 if (type
== AST_POW
&& children
[0]->isConst() && children
[1]->isConst()) {
3358 newNode
= new AstNode(AST_REALVALUE
);
3359 newNode
->realvalue
= pow(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
));
3362 if (0) { case AST_LT
: const_func
= RTLIL::const_lt
; }
3363 if (0) { case AST_LE
: const_func
= RTLIL::const_le
; }
3364 if (0) { case AST_EQ
: const_func
= RTLIL::const_eq
; }
3365 if (0) { case AST_NE
: const_func
= RTLIL::const_ne
; }
3366 if (0) { case AST_EQX
: const_func
= RTLIL::const_eqx
; }
3367 if (0) { case AST_NEX
: const_func
= RTLIL::const_nex
; }
3368 if (0) { case AST_GE
: const_func
= RTLIL::const_ge
; }
3369 if (0) { case AST_GT
: const_func
= RTLIL::const_gt
; }
3370 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3371 int cmp_width
= max(children
[0]->bits
.size(), children
[1]->bits
.size());
3372 bool cmp_signed
= children
[0]->is_signed
&& children
[1]->is_signed
;
3373 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(cmp_width
, cmp_signed
),
3374 children
[1]->bitsAsConst(cmp_width
, cmp_signed
), cmp_signed
, cmp_signed
, 1);
3375 newNode
= mkconst_bits(y
.bits
, false);
3377 if (children
[0]->isConst() && children
[1]->isConst()) {
3378 bool cmp_signed
= (children
[0]->type
== AST_REALVALUE
|| children
[0]->is_signed
) && (children
[1]->type
== AST_REALVALUE
|| children
[1]->is_signed
);
3380 case AST_LT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) < children
[1]->asReal(cmp_signed
), false, 1); break;
3381 case AST_LE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) <= children
[1]->asReal(cmp_signed
), false, 1); break;
3382 case AST_EQ
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
3383 case AST_NE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
3384 case AST_EQX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
3385 case AST_NEX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
3386 case AST_GE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) >= children
[1]->asReal(cmp_signed
), false, 1); break;
3387 case AST_GT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) > children
[1]->asReal(cmp_signed
), false, 1); break;
3388 default: log_abort();
3392 if (0) { case AST_ADD
: const_func
= RTLIL::const_add
; }
3393 if (0) { case AST_SUB
: const_func
= RTLIL::const_sub
; }
3394 if (0) { case AST_MUL
: const_func
= RTLIL::const_mul
; }
3395 if (0) { case AST_DIV
: const_func
= RTLIL::const_div
; }
3396 if (0) { case AST_MOD
: const_func
= RTLIL::const_mod
; }
3397 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3398 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3399 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
3400 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3402 if (children
[0]->isConst() && children
[1]->isConst()) {
3403 newNode
= new AstNode(AST_REALVALUE
);
3405 case AST_ADD
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) + children
[1]->asReal(sign_hint
); break;
3406 case AST_SUB
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) - children
[1]->asReal(sign_hint
); break;
3407 case AST_MUL
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) * children
[1]->asReal(sign_hint
); break;
3408 case AST_DIV
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) / children
[1]->asReal(sign_hint
); break;
3409 case AST_MOD
: newNode
->realvalue
= fmod(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
)); break;
3410 default: log_abort();
3414 if (0) { case AST_SELFSZ
: const_func
= RTLIL::const_pos
; }
3415 if (0) { case AST_POS
: const_func
= RTLIL::const_pos
; }
3416 if (0) { case AST_NEG
: const_func
= RTLIL::const_neg
; }
3417 if (children
[0]->type
== AST_CONSTANT
) {
3418 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
3419 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3421 if (children
[0]->isConst()) {
3422 newNode
= new AstNode(AST_REALVALUE
);
3423 if (type
== AST_NEG
)
3424 newNode
->realvalue
= -children
[0]->asReal(sign_hint
);
3426 newNode
->realvalue
= +children
[0]->asReal(sign_hint
);
3430 if (children
[0]->isConst())
3432 bool found_sure_true
= false;
3433 bool found_maybe_true
= false;
3435 if (children
[0]->type
== AST_CONSTANT
)
3436 for (auto &bit
: children
[0]->bits
) {
3437 if (bit
== RTLIL::State::S1
)
3438 found_sure_true
= true;
3439 if (bit
> RTLIL::State::S1
)
3440 found_maybe_true
= true;
3443 found_sure_true
= children
[0]->asReal(sign_hint
) != 0;
3445 AstNode
*choice
= NULL
, *not_choice
= NULL
;
3446 if (found_sure_true
)
3447 choice
= children
[1], not_choice
= children
[2];
3448 else if (!found_maybe_true
)
3449 choice
= children
[2], not_choice
= children
[1];
3451 if (choice
!= NULL
) {
3452 if (choice
->type
== AST_CONSTANT
) {
3453 int other_width_hint
= width_hint
;
3454 bool other_sign_hint
= sign_hint
, other_real
= false;
3455 not_choice
->detectSignWidth(other_width_hint
, other_sign_hint
, &other_real
);
3457 newNode
= new AstNode(AST_REALVALUE
);
3458 choice
->detectSignWidth(width_hint
, sign_hint
);
3459 newNode
->realvalue
= choice
->asReal(sign_hint
);
3461 RTLIL::Const y
= choice
->bitsAsConst(width_hint
, sign_hint
);
3462 if (choice
->is_string
&& y
.bits
.size() % 8 == 0 && sign_hint
== false)
3463 newNode
= mkconst_str(y
.bits
);
3465 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3468 if (choice
->isConst()) {
3469 newNode
= choice
->clone();
3471 } else if (children
[1]->type
== AST_CONSTANT
&& children
[2]->type
== AST_CONSTANT
) {
3472 RTLIL::Const a
= children
[1]->bitsAsConst(width_hint
, sign_hint
);
3473 RTLIL::Const b
= children
[2]->bitsAsConst(width_hint
, sign_hint
);
3474 log_assert(a
.bits
.size() == b
.bits
.size());
3475 for (size_t i
= 0; i
< a
.bits
.size(); i
++)
3476 if (a
.bits
[i
] != b
.bits
[i
])
3477 a
.bits
[i
] = RTLIL::State::Sx
;
3478 newNode
= mkconst_bits(a
.bits
, sign_hint
);
3479 } else if (children
[1]->isConst() && children
[2]->isConst()) {
3480 newNode
= new AstNode(AST_REALVALUE
);
3481 if (children
[1]->asReal(sign_hint
) == children
[2]->asReal(sign_hint
))
3482 newNode
->realvalue
= children
[1]->asReal(sign_hint
);
3484 // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
3485 // the data type in question should be returned if the ?: is ambiguous. The
3486 // value in Table 7-1 for the 'real' type is 0.0.
3487 newNode
->realvalue
= 0.0;
3492 if (children
.at(0)->type
== AST_CONSTANT
&& children
.at(1)->type
== AST_CONSTANT
) {
3493 int width
= children
[0]->bitsAsConst().as_int();
3494 RTLIL::Const val
= children
[1]->bitsAsConst(width
);
3495 newNode
= mkconst_bits(val
.bits
, children
[1]->is_signed
);
3499 string_op
= !children
.empty();
3500 for (auto it
= children
.begin(); it
!= children
.end(); it
++) {
3501 if ((*it
)->type
!= AST_CONSTANT
)
3503 if (!(*it
)->is_string
)
3505 tmp_bits
.insert(tmp_bits
.end(), (*it
)->bits
.begin(), (*it
)->bits
.end());
3507 newNode
= string_op
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
3510 if (children
.at(0)->type
!= AST_CONSTANT
|| children
.at(1)->type
!= AST_CONSTANT
)
3512 for (int i
= 0; i
< children
[0]->bitsAsConst().as_int(); i
++)
3513 tmp_bits
.insert(tmp_bits
.end(), children
.at(1)->bits
.begin(), children
.at(1)->bits
.end());
3514 newNode
= children
.at(1)->is_string
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
3522 // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
3525 // fprintf(stderr, "----\n");
3526 // dumpAst(stderr, "- ");
3527 // newNode->dumpAst(stderr, "+ ");
3528 log_assert(newNode
!= NULL
);
3529 newNode
->filename
= filename
;
3530 newNode
->location
= location
;
3531 newNode
->cloneInto(this);
3533 did_something
= true;
3539 recursion_counter
--;
3540 return did_something
;
3543 static void replace_result_wire_name_in_function(AstNode
*node
, std::string
&from
, std::string
&to
)
3545 for (auto &it
: node
->children
)
3546 replace_result_wire_name_in_function(it
, from
, to
);
3547 if (node
->str
== from
)
3551 // replace a readmem[bh] TCALL ast node with a block of memory assignments
3552 AstNode
*AstNode::readmem(bool is_readmemh
, std::string mem_filename
, AstNode
*memory
, int start_addr
, int finish_addr
, bool unconditional_init
)
3554 int mem_width
, mem_size
, addr_bits
;
3555 memory
->meminfo(mem_width
, mem_size
, addr_bits
);
3557 AstNode
*block
= new AstNode(AST_BLOCK
);
3559 AstNode
*meminit
= nullptr;
3560 int next_meminit_cursor
=0;
3561 vector
<State
> meminit_bits
;
3565 f
.open(mem_filename
.c_str());
3572 std::string path
= filename
.substr(0, filename
.find_last_of(slash
)+1);
3573 f
.open(path
+ mem_filename
.c_str());
3574 yosys_input_files
.insert(path
+ mem_filename
);
3576 yosys_input_files
.insert(mem_filename
);
3578 if (f
.fail() || GetSize(mem_filename
) == 0)
3579 log_file_error(filename
, location
.first_line
, "Can not open file `%s` for %s.\n", mem_filename
.c_str(), str
.c_str());
3581 log_assert(GetSize(memory
->children
) == 2 && memory
->children
[1]->type
== AST_RANGE
&& memory
->children
[1]->range_valid
);
3582 int range_left
= memory
->children
[1]->range_left
, range_right
= memory
->children
[1]->range_right
;
3583 int range_min
= min(range_left
, range_right
), range_max
= max(range_left
, range_right
);
3586 start_addr
= range_min
;
3588 if (finish_addr
< 0)
3589 finish_addr
= range_max
+ 1;
3591 bool in_comment
= false;
3592 int increment
= start_addr
<= finish_addr
? +1 : -1;
3593 int cursor
= start_addr
;
3597 std::string line
, token
;
3598 std::getline(f
, line
);
3600 for (int i
= 0; i
< GetSize(line
); i
++) {
3601 if (in_comment
&& line
.compare(i
, 2, "*/") == 0) {
3607 if (!in_comment
&& line
.compare(i
, 2, "/*") == 0)
3615 token
= next_token(line
, " \t\r\n");
3616 if (token
.empty() || token
.compare(0, 2, "//") == 0)
3619 if (token
[0] == '@') {
3620 token
= token
.substr(1);
3621 const char *nptr
= token
.c_str();
3623 cursor
= strtol(nptr
, &endptr
, 16);
3624 if (!*nptr
|| *endptr
)
3625 log_file_error(filename
, location
.first_line
, "Can not parse address `%s` for %s.\n", nptr
, str
.c_str());
3629 AstNode
*value
= VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width
, is_readmemh
? 'h' : 'b') + token
);
3631 if (unconditional_init
)
3633 if (meminit
== nullptr || cursor
!= next_meminit_cursor
)
3635 if (meminit
!= nullptr) {
3636 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
3637 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
3640 meminit
= new AstNode(AST_MEMINIT
);
3641 meminit
->children
.push_back(AstNode::mkconst_int(cursor
, false));
3642 meminit
->children
.push_back(nullptr);
3643 meminit
->children
.push_back(nullptr);
3644 meminit
->str
= memory
->str
;
3645 meminit
->id2ast
= memory
;
3646 meminit_bits
.clear();
3649 current_ast_mod
->children
.push_back(meminit
);
3650 next_meminit_cursor
= cursor
;
3654 next_meminit_cursor
++;
3655 meminit_bits
.insert(meminit_bits
.end(), value
->bits
.begin(), value
->bits
.end());
3660 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
, false))), value
));
3661 block
->children
.back()->children
[0]->str
= memory
->str
;
3662 block
->children
.back()->children
[0]->id2ast
= memory
;
3663 block
->children
.back()->children
[0]->was_checked
= true;
3666 cursor
+= increment
;
3667 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
3671 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
3675 if (meminit
!= nullptr) {
3676 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
3677 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
3683 // annotate the names of all wires and other named objects in a generate block
3684 void AstNode::expand_genblock(std::string index_var
, std::string prefix
, std::map
<std::string
, std::string
> &name_map
)
3686 if (!index_var
.empty() && type
== AST_IDENTIFIER
&& str
== index_var
) {
3687 if (children
.empty()) {
3688 current_scope
[index_var
]->children
[0]->cloneInto(this);
3690 AstNode
*p
= new AstNode(AST_LOCALPARAM
, current_scope
[index_var
]->children
[0]->clone());
3691 p
->str
= stringf("$genval$%d", autoidx
++);
3692 current_ast_mod
->children
.push_back(p
);
3698 if ((type
== AST_IDENTIFIER
|| type
== AST_FCALL
|| type
== AST_TCALL
|| type
== AST_WIRETYPE
) && name_map
.count(str
) > 0)
3699 str
= name_map
[str
];
3701 std::map
<std::string
, std::string
> backup_name_map
;
3703 for (size_t i
= 0; i
< children
.size(); i
++) {
3704 AstNode
*child
= children
[i
];
3705 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
||
3706 child
->type
== AST_FUNCTION
|| child
->type
== AST_TASK
|| child
->type
== AST_CELL
|| child
->type
== AST_TYPEDEF
|| child
->type
== AST_ENUM_ITEM
) {
3707 if (backup_name_map
.size() == 0)
3708 backup_name_map
= name_map
;
3709 std::string new_name
= prefix
[0] == '\\' ? prefix
.substr(1) : prefix
;
3710 size_t pos
= child
->str
.rfind('.');
3711 if (pos
== std::string::npos
)
3712 pos
= child
->str
[0] == '\\' && prefix
[0] == '\\' ? 1 : 0;
3715 new_name
= child
->str
.substr(0, pos
) + new_name
+ child
->str
.substr(pos
);
3716 if (new_name
[0] != '$' && new_name
[0] != '\\')
3717 new_name
= prefix
[0] + new_name
;
3718 name_map
[child
->str
] = new_name
;
3719 if (child
->type
== AST_FUNCTION
)
3720 replace_result_wire_name_in_function(child
, child
->str
, new_name
);
3722 child
->str
= new_name
;
3723 current_scope
[new_name
] = child
;
3725 if (child
->type
== AST_ENUM
){
3726 current_scope
[child
->str
] = child
;
3727 for (auto enode
: child
->children
){
3728 log_assert(enode
->type
== AST_ENUM_ITEM
);
3729 if (backup_name_map
.size() == 0)
3730 backup_name_map
= name_map
;
3731 std::string new_name
= prefix
[0] == '\\' ? prefix
.substr(1) : prefix
;
3732 size_t pos
= enode
->str
.rfind('.');
3733 if (pos
== std::string::npos
)
3734 pos
= enode
->str
[0] == '\\' && prefix
[0] == '\\' ? 1 : 0;
3737 new_name
= enode
->str
.substr(0, pos
) + new_name
+ enode
->str
.substr(pos
);
3738 if (new_name
[0] != '$' && new_name
[0] != '\\')
3739 new_name
= prefix
[0] + new_name
;
3740 name_map
[enode
->str
] = new_name
;
3742 enode
->str
= new_name
;
3743 current_scope
[new_name
] = enode
;
3748 for (size_t i
= 0; i
< children
.size(); i
++) {
3749 AstNode
*child
= children
[i
];
3750 // AST_PREFIX member names should not be prefixed; a nested AST_PREFIX
3751 // still needs to recursed-into
3752 if (type
== AST_PREFIX
&& i
== 1 && child
->type
== AST_IDENTIFIER
)
3754 if (child
->type
!= AST_FUNCTION
&& child
->type
!= AST_TASK
)
3755 child
->expand_genblock(index_var
, prefix
, name_map
);
3759 if (backup_name_map
.size() > 0)
3760 name_map
.swap(backup_name_map
);
3763 // rename stuff (used when tasks of functions are instantiated)
3764 void AstNode::replace_ids(const std::string
&prefix
, const std::map
<std::string
, std::string
> &rules
)
3766 if (type
== AST_BLOCK
)
3768 std::map
<std::string
, std::string
> new_rules
= rules
;
3769 std::string new_prefix
= prefix
+ str
;
3771 for (auto child
: children
)
3772 if (child
->type
== AST_WIRE
) {
3773 new_rules
[child
->str
] = new_prefix
+ child
->str
;
3774 child
->str
= new_prefix
+ child
->str
;
3777 for (auto child
: children
)
3778 if (child
->type
!= AST_WIRE
)
3779 child
->replace_ids(new_prefix
, new_rules
);
3783 if (type
== AST_IDENTIFIER
&& rules
.count(str
) > 0)
3784 str
= rules
.at(str
);
3785 for (auto child
: children
)
3786 child
->replace_ids(prefix
, rules
);
3790 // helper function for mem2reg_as_needed_pass1
3791 static void mark_memories_assign_lhs_complex(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
3792 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, AstNode
*that
)
3794 for (auto &child
: that
->children
)
3795 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, child
);
3797 if (that
->type
== AST_IDENTIFIER
&& that
->id2ast
&& that
->id2ast
->type
== AST_MEMORY
) {
3798 AstNode
*mem
= that
->id2ast
;
3799 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_CMPLX_LHS
))
3800 mem2reg_places
[mem
].insert(stringf("%s:%d", that
->filename
.c_str(), that
->location
.first_line
));
3801 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CMPLX_LHS
;
3805 // find memories that should be replaced by registers
3806 void AstNode::mem2reg_as_needed_pass1(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
3807 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, dict
<AstNode
*, uint32_t> &proc_flags
, uint32_t &flags
)
3809 uint32_t children_flags
= 0;
3810 int lhs_children_counter
= 0;
3812 if (type
== AST_TYPEDEF
)
3813 return; // don't touch content of typedefs
3815 if (type
== AST_ASSIGN
|| type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
)
3817 // mark all memories that are used in a complex expression on the left side of an assignment
3818 for (auto &lhs_child
: children
[0]->children
)
3819 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, lhs_child
);
3821 if (children
[0]->type
== AST_IDENTIFIER
&& children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
)
3823 AstNode
*mem
= children
[0]->id2ast
;
3825 // activate mem2reg if this is assigned in an async proc
3826 if (flags
& AstNode::MEM2REG_FL_ASYNC
) {
3827 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ASYNC
))
3828 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3829 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ASYNC
;
3832 // remember if this is assigned blocking (=)
3833 if (type
== AST_ASSIGN_EQ
) {
3834 if (!(proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
))
3835 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3836 proc_flags
[mem
] |= AstNode::MEM2REG_FL_EQ1
;
3839 // for proper (non-init) writes: remember if this is a constant index or not
3840 if ((flags
& MEM2REG_FL_INIT
) == 0) {
3841 if (children
[0]->children
.size() && children
[0]->children
[0]->type
== AST_RANGE
&& children
[0]->children
[0]->children
.size()) {
3842 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
)
3843 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CONST_LHS
;
3845 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_VAR_LHS
;
3849 // remember where this is
3850 if (flags
& MEM2REG_FL_INIT
) {
3851 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_INIT
))
3852 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3853 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_INIT
;
3855 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ELSE
))
3856 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3857 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ELSE
;
3861 lhs_children_counter
= 1;
3864 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
)
3866 AstNode
*mem
= id2ast
;
3868 // flag if used after blocking assignment (in same proc)
3869 if ((proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
) && !(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_EQ2
)) {
3870 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3871 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_EQ2
;
3875 // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg' or 'logic'
3876 if (type
== AST_MEMORY
&& (get_bool_attribute(ID::mem2reg
) || (flags
& AstNode::MEM2REG_FL_ALL
) || !(is_reg
|| is_logic
)))
3877 mem2reg_candidates
[this] |= AstNode::MEM2REG_FL_FORCED
;
3879 if (type
== AST_MODULE
&& get_bool_attribute(ID::mem2reg
))
3880 children_flags
|= AstNode::MEM2REG_FL_ALL
;
3882 dict
<AstNode
*, uint32_t> *proc_flags_p
= NULL
;
3884 if (type
== AST_ALWAYS
) {
3885 int count_edge_events
= 0;
3886 for (auto child
: children
)
3887 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
3888 count_edge_events
++;
3889 if (count_edge_events
!= 1)
3890 children_flags
|= AstNode::MEM2REG_FL_ASYNC
;
3891 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
3894 if (type
== AST_INITIAL
) {
3895 children_flags
|= AstNode::MEM2REG_FL_INIT
;
3896 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
3899 uint32_t backup_flags
= flags
;
3900 flags
|= children_flags
;
3901 log_assert((flags
& ~0x000000ff) == 0);
3903 for (auto child
: children
)
3905 if (lhs_children_counter
> 0) {
3906 lhs_children_counter
--;
3907 if (child
->children
.size() && child
->children
[0]->type
== AST_RANGE
&& child
->children
[0]->children
.size()) {
3908 for (auto c
: child
->children
[0]->children
) {
3910 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
3912 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
3917 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
3919 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
3922 flags
&= ~children_flags
| backup_flags
;
3926 for (auto it
: *proc_flags_p
)
3927 log_assert((it
.second
& ~0xff000000) == 0);
3929 delete proc_flags_p
;
3933 bool AstNode::mem2reg_check(pool
<AstNode
*> &mem2reg_set
)
3935 if (type
!= AST_IDENTIFIER
|| !id2ast
|| !mem2reg_set
.count(id2ast
))
3938 if (children
.empty() || children
[0]->type
!= AST_RANGE
|| GetSize(children
[0]->children
) != 1)
3939 log_file_error(filename
, location
.first_line
, "Invalid array access.\n");
3944 void AstNode::mem2reg_remove(pool
<AstNode
*> &mem2reg_set
, vector
<AstNode
*> &delnodes
)
3946 log_assert(mem2reg_set
.count(this) == 0);
3948 if (mem2reg_set
.count(id2ast
))
3951 for (size_t i
= 0; i
< children
.size(); i
++) {
3952 if (mem2reg_set
.count(children
[i
]) > 0) {
3953 delnodes
.push_back(children
[i
]);
3954 children
.erase(children
.begin() + (i
--));
3956 children
[i
]->mem2reg_remove(mem2reg_set
, delnodes
);
3961 // actually replace memories with registers
3962 bool AstNode::mem2reg_as_needed_pass2(pool
<AstNode
*> &mem2reg_set
, AstNode
*mod
, AstNode
*block
, AstNode
*&async_block
)
3964 bool did_something
= false;
3966 if (type
== AST_BLOCK
)
3969 if (type
== AST_FUNCTION
|| type
== AST_TASK
)
3972 if (type
== AST_TYPEDEF
)
3975 if (type
== AST_MEMINIT
&& id2ast
&& mem2reg_set
.count(id2ast
))
3977 log_assert(children
[0]->type
== AST_CONSTANT
);
3978 log_assert(children
[1]->type
== AST_CONSTANT
);
3979 log_assert(children
[2]->type
== AST_CONSTANT
);
3981 int cursor
= children
[0]->asInt(false);
3982 Const data
= children
[1]->bitsAsConst();
3983 int length
= children
[2]->asInt(false);
3987 AstNode
*block
= new AstNode(AST_INITIAL
, new AstNode(AST_BLOCK
));
3988 mod
->children
.push_back(block
);
3989 block
= block
->children
[0];
3991 int wordsz
= GetSize(data
) / length
;
3993 for (int i
= 0; i
< length
; i
++) {
3994 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+i
, false))), mkconst_bits(data
.extract(i
*wordsz
, wordsz
).bits
, false)));
3995 block
->children
.back()->children
[0]->str
= str
;
3996 block
->children
.back()->children
[0]->id2ast
= id2ast
;
3997 block
->children
.back()->children
[0]->was_checked
= true;
4001 AstNode
*newNode
= new AstNode(AST_NONE
);
4002 newNode
->cloneInto(this);
4005 did_something
= true;
4008 if (type
== AST_ASSIGN
&& block
== NULL
&& children
[0]->mem2reg_check(mem2reg_set
))
4010 if (async_block
== NULL
) {
4011 async_block
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
4012 mod
->children
.push_back(async_block
);
4015 AstNode
*newNode
= clone();
4016 newNode
->type
= AST_ASSIGN_EQ
;
4017 newNode
->children
[0]->was_checked
= true;
4018 async_block
->children
[0]->children
.push_back(newNode
);
4020 newNode
= new AstNode(AST_NONE
);
4021 newNode
->cloneInto(this);
4024 did_something
= true;
4027 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->mem2reg_check(mem2reg_set
) &&
4028 children
[0]->children
[0]->children
[0]->type
!= AST_CONSTANT
)
4030 std::stringstream sstr
;
4031 sstr
<< "$mem2reg_wr$" << children
[0]->str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
4032 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
4034 int mem_width
, mem_size
, addr_bits
;
4035 bool mem_signed
= children
[0]->id2ast
->is_signed
;
4036 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
4038 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
4039 wire_addr
->str
= id_addr
;
4040 wire_addr
->is_reg
= true;
4041 wire_addr
->was_checked
= true;
4042 wire_addr
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
4043 mod
->children
.push_back(wire_addr
);
4044 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
4046 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
4047 wire_data
->str
= id_data
;
4048 wire_data
->is_reg
= true;
4049 wire_data
->was_checked
= true;
4050 wire_data
->is_signed
= mem_signed
;
4051 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
4052 mod
->children
.push_back(wire_data
);
4053 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
4055 log_assert(block
!= NULL
);
4056 size_t assign_idx
= 0;
4057 while (assign_idx
< block
->children
.size() && block
->children
[assign_idx
] != this)
4059 log_assert(assign_idx
< block
->children
.size());
4061 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
4062 assign_addr
->children
[0]->str
= id_addr
;
4063 assign_addr
->children
[0]->was_checked
= true;
4064 block
->children
.insert(block
->children
.begin()+assign_idx
+1, assign_addr
);
4066 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
4067 case_node
->children
[0]->str
= id_addr
;
4068 for (int i
= 0; i
< mem_size
; i
++) {
4069 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->children
[0]->integer
) != i
)
4071 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
4072 AstNode
*assign_reg
= new AstNode(type
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
4073 if (children
[0]->children
.size() == 2)
4074 assign_reg
->children
[0]->children
.push_back(children
[0]->children
[1]->clone());
4075 assign_reg
->children
[0]->str
= stringf("%s[%d]", children
[0]->str
.c_str(), i
);
4076 assign_reg
->children
[1]->str
= id_data
;
4077 cond_node
->children
[1]->children
.push_back(assign_reg
);
4078 case_node
->children
.push_back(cond_node
);
4080 block
->children
.insert(block
->children
.begin()+assign_idx
+2, case_node
);
4082 children
[0]->delete_children();
4083 children
[0]->range_valid
= false;
4084 children
[0]->id2ast
= NULL
;
4085 children
[0]->str
= id_data
;
4086 type
= AST_ASSIGN_EQ
;
4087 children
[0]->was_checked
= true;
4089 did_something
= true;
4092 if (mem2reg_check(mem2reg_set
))
4094 AstNode
*bit_part_sel
= NULL
;
4095 if (children
.size() == 2)
4096 bit_part_sel
= children
[1]->clone();
4098 if (children
[0]->children
[0]->type
== AST_CONSTANT
)
4100 int id
= children
[0]->children
[0]->integer
;
4101 str
= stringf("%s[%d]", str
.c_str(), id
);
4104 range_valid
= false;
4109 std::stringstream sstr
;
4110 sstr
<< "$mem2reg_rd$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
4111 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
4113 int mem_width
, mem_size
, addr_bits
;
4114 bool mem_signed
= id2ast
->is_signed
;
4115 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
4117 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
4118 wire_addr
->str
= id_addr
;
4119 wire_addr
->is_reg
= true;
4120 wire_addr
->was_checked
= true;
4122 wire_addr
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
4123 mod
->children
.push_back(wire_addr
);
4124 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
4126 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
4127 wire_data
->str
= id_data
;
4128 wire_data
->is_reg
= true;
4129 wire_data
->was_checked
= true;
4130 wire_data
->is_signed
= mem_signed
;
4132 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
4133 mod
->children
.push_back(wire_data
);
4134 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
4136 AstNode
*assign_addr
= new AstNode(block
? AST_ASSIGN_EQ
: AST_ASSIGN
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->clone());
4137 assign_addr
->children
[0]->str
= id_addr
;
4138 assign_addr
->children
[0]->was_checked
= true;
4140 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
4141 case_node
->children
[0]->str
= id_addr
;
4143 for (int i
= 0; i
< mem_size
; i
++) {
4144 if (children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->integer
) != i
)
4146 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
4147 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
4148 assign_reg
->children
[0]->str
= id_data
;
4149 assign_reg
->children
[0]->was_checked
= true;
4150 assign_reg
->children
[1]->str
= stringf("%s[%d]", str
.c_str(), i
);
4151 cond_node
->children
[1]->children
.push_back(assign_reg
);
4152 case_node
->children
.push_back(cond_node
);
4155 std::vector
<RTLIL::State
> x_bits
;
4156 for (int i
= 0; i
< mem_width
; i
++)
4157 x_bits
.push_back(RTLIL::State::Sx
);
4159 AstNode
*cond_node
= new AstNode(AST_COND
, new AstNode(AST_DEFAULT
), new AstNode(AST_BLOCK
));
4160 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), AstNode::mkconst_bits(x_bits
, false));
4161 assign_reg
->children
[0]->str
= id_data
;
4162 assign_reg
->children
[0]->was_checked
= true;
4163 cond_node
->children
[1]->children
.push_back(assign_reg
);
4164 case_node
->children
.push_back(cond_node
);
4168 size_t assign_idx
= 0;
4169 while (assign_idx
< block
->children
.size() && !block
->children
[assign_idx
]->contains(this))
4171 log_assert(assign_idx
< block
->children
.size());
4172 block
->children
.insert(block
->children
.begin()+assign_idx
, case_node
);
4173 block
->children
.insert(block
->children
.begin()+assign_idx
, assign_addr
);
4177 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
4178 proc
->children
[0]->children
.push_back(case_node
);
4179 mod
->children
.push_back(proc
);
4180 mod
->children
.push_back(assign_addr
);
4184 range_valid
= false;
4190 children
.push_back(bit_part_sel
);
4192 did_something
= true;
4195 log_assert(id2ast
== NULL
|| mem2reg_set
.count(id2ast
) == 0);
4197 auto children_list
= children
;
4198 for (size_t i
= 0; i
< children_list
.size(); i
++)
4199 if (children_list
[i
]->mem2reg_as_needed_pass2(mem2reg_set
, mod
, block
, async_block
))
4200 did_something
= true;
4202 return did_something
;
4205 // calculate memory dimensions
4206 void AstNode::meminfo(int &mem_width
, int &mem_size
, int &addr_bits
)
4208 log_assert(type
== AST_MEMORY
);
4210 mem_width
= children
[0]->range_left
- children
[0]->range_right
+ 1;
4211 mem_size
= children
[1]->range_left
- children
[1]->range_right
;
4215 mem_size
+= min(children
[1]->range_left
, children
[1]->range_right
) + 1;
4218 while ((1 << addr_bits
) < mem_size
)
4222 bool AstNode::detect_latch(const std::string
&var
)
4227 for (auto &c
: children
)
4237 if (!c
->detect_latch(var
))
4246 for (auto &c
: children
)
4247 if (!c
->detect_latch(var
))
4253 for (auto &c
: children
) {
4254 if (c
->type
== AST_COND
) {
4255 if (c
->children
.at(1)->detect_latch(var
))
4259 if (c
->type
== AST_DEFAULT
) {
4260 if (c
->children
.at(0)->detect_latch(var
))
4269 if (children
.at(0)->type
== AST_IDENTIFIER
&&
4270 children
.at(0)->children
.empty() && children
.at(0)->str
== var
)
4278 bool AstNode::has_const_only_constructs(bool &recommend_const_eval
)
4280 if (type
== AST_FOR
)
4281 recommend_const_eval
= true;
4282 if (type
== AST_WHILE
|| type
== AST_REPEAT
)
4284 if (type
== AST_FCALL
&& current_scope
.count(str
))
4285 if (current_scope
[str
]->has_const_only_constructs(recommend_const_eval
))
4287 for (auto child
: children
)
4288 if (child
->AstNode::has_const_only_constructs(recommend_const_eval
))
4293 bool AstNode::is_simple_const_expr()
4295 if (type
== AST_IDENTIFIER
)
4297 for (auto child
: children
)
4298 if (!child
->is_simple_const_expr())
4303 // helper function for AstNode::eval_const_function()
4304 void AstNode::replace_variables(std::map
<std::string
, AstNode::varinfo_t
> &variables
, AstNode
*fcall
)
4306 if (type
== AST_IDENTIFIER
&& variables
.count(str
)) {
4307 int offset
= variables
.at(str
).offset
, width
= variables
.at(str
).val
.bits
.size();
4308 if (!children
.empty()) {
4309 if (children
.size() != 1 || children
.at(0)->type
!= AST_RANGE
)
4310 log_file_error(filename
, location
.first_line
, "Memory access in constant function is not supported\n%s:%d.%d-%d.%d: ...called from here.\n",
4311 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4312 children
.at(0)->replace_variables(variables
, fcall
);
4313 while (simplify(true, false, false, 1, -1, false, true)) { }
4314 if (!children
.at(0)->range_valid
)
4315 log_file_error(filename
, location
.first_line
, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
4316 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4317 offset
= min(children
.at(0)->range_left
, children
.at(0)->range_right
);
4318 width
= min(std::abs(children
.at(0)->range_left
- children
.at(0)->range_right
) + 1, width
);
4320 offset
-= variables
.at(str
).offset
;
4321 std::vector
<RTLIL::State
> &var_bits
= variables
.at(str
).val
.bits
;
4322 std::vector
<RTLIL::State
> new_bits(var_bits
.begin() + offset
, var_bits
.begin() + offset
+ width
);
4323 AstNode
*newNode
= mkconst_bits(new_bits
, variables
.at(str
).is_signed
);
4324 newNode
->cloneInto(this);
4329 for (auto &child
: children
)
4330 child
->replace_variables(variables
, fcall
);
4333 // evaluate functions with all-const arguments
4334 AstNode
*AstNode::eval_const_function(AstNode
*fcall
)
4336 std::map
<std::string
, AstNode
*> backup_scope
;
4337 std::map
<std::string
, AstNode::varinfo_t
> variables
;
4338 AstNode
*block
= new AstNode(AST_BLOCK
);
4341 for (auto child
: children
)
4343 if (child
->type
== AST_WIRE
)
4345 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
4346 if (!child
->range_valid
)
4347 log_file_error(child
->filename
, child
->location
.first_line
, "Can't determine size of variable %s\n%s:%d.%d-%d.%d: ... called from here.\n",
4348 child
->str
.c_str(), fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4349 variables
[child
->str
].val
= RTLIL::Const(RTLIL::State::Sx
, abs(child
->range_left
- child
->range_right
)+1);
4350 variables
[child
->str
].offset
= min(child
->range_left
, child
->range_right
);
4351 variables
[child
->str
].is_signed
= child
->is_signed
;
4352 if (child
->is_input
&& argidx
< fcall
->children
.size()) {
4353 int width
= variables
[child
->str
].val
.bits
.size();
4354 auto* arg_node
= fcall
->children
.at(argidx
++);
4355 if (arg_node
->type
== AST_CONSTANT
) {
4356 variables
[child
->str
].val
= arg_node
->bitsAsConst(width
);
4358 log_assert(arg_node
->type
== AST_REALVALUE
);
4359 variables
[child
->str
].val
= arg_node
->realAsConst(width
);
4362 backup_scope
[child
->str
] = current_scope
[child
->str
];
4363 current_scope
[child
->str
] = child
;
4367 block
->children
.push_back(child
->clone());
4370 log_assert(variables
.count(str
) != 0);
4372 while (!block
->children
.empty())
4374 AstNode
*stmt
= block
->children
.front();
4377 log("-----------------------------------\n");
4378 for (auto &it
: variables
)
4379 log("%20s %40s\n", it
.first
.c_str(), log_signal(it
.second
.val
));
4380 stmt
->dumpAst(NULL
, "stmt> ");
4383 if (stmt
->type
== AST_ASSIGN_EQ
)
4385 if (stmt
->children
.at(0)->type
== AST_IDENTIFIER
&& stmt
->children
.at(0)->children
.size() != 0 &&
4386 stmt
->children
.at(0)->children
.at(0)->type
== AST_RANGE
)
4387 stmt
->children
.at(0)->children
.at(0)->replace_variables(variables
, fcall
);
4388 stmt
->children
.at(1)->replace_variables(variables
, fcall
);
4389 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
4391 if (stmt
->type
!= AST_ASSIGN_EQ
)
4394 if (stmt
->children
.at(1)->type
!= AST_CONSTANT
)
4395 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here. X\n",
4396 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4398 if (stmt
->children
.at(0)->type
!= AST_IDENTIFIER
)
4399 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Unsupported composite left hand side in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4400 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4402 if (!variables
.count(stmt
->children
.at(0)->str
))
4403 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Assignment to non-local variable in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4404 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4406 if (stmt
->children
.at(0)->children
.empty()) {
4407 variables
[stmt
->children
.at(0)->str
].val
= stmt
->children
.at(1)->bitsAsConst(variables
[stmt
->children
.at(0)->str
].val
.bits
.size());
4409 AstNode
*range
= stmt
->children
.at(0)->children
.at(0);
4410 if (!range
->range_valid
)
4411 log_file_error(range
->filename
, range
->location
.first_line
, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
4412 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4413 int offset
= min(range
->range_left
, range
->range_right
);
4414 int width
= std::abs(range
->range_left
- range
->range_right
) + 1;
4415 varinfo_t
&v
= variables
[stmt
->children
.at(0)->str
];
4416 RTLIL::Const r
= stmt
->children
.at(1)->bitsAsConst(v
.val
.bits
.size());
4417 for (int i
= 0; i
< width
; i
++)
4418 v
.val
.bits
.at(i
+offset
-v
.offset
) = r
.bits
.at(i
);
4421 delete block
->children
.front();
4422 block
->children
.erase(block
->children
.begin());
4426 if (stmt
->type
== AST_FOR
)
4428 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(0));
4429 stmt
->children
.at(3)->children
.push_back(stmt
->children
.at(2));
4430 stmt
->children
.erase(stmt
->children
.begin() + 2);
4431 stmt
->children
.erase(stmt
->children
.begin());
4432 stmt
->type
= AST_WHILE
;
4436 if (stmt
->type
== AST_WHILE
)
4438 AstNode
*cond
= stmt
->children
.at(0)->clone();
4439 cond
->replace_variables(variables
, fcall
);
4440 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
4442 if (cond
->type
!= AST_CONSTANT
)
4443 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4444 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4446 if (cond
->asBool()) {
4447 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
4449 delete block
->children
.front();
4450 block
->children
.erase(block
->children
.begin());
4457 if (stmt
->type
== AST_REPEAT
)
4459 AstNode
*num
= stmt
->children
.at(0)->clone();
4460 num
->replace_variables(variables
, fcall
);
4461 while (num
->simplify(true, false, false, 1, -1, false, true)) { }
4463 if (num
->type
!= AST_CONSTANT
)
4464 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4465 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4467 block
->children
.erase(block
->children
.begin());
4468 for (int i
= 0; i
< num
->bitsAsConst().as_int(); i
++)
4469 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
4476 if (stmt
->type
== AST_CASE
)
4478 AstNode
*expr
= stmt
->children
.at(0)->clone();
4479 expr
->replace_variables(variables
, fcall
);
4480 while (expr
->simplify(true, false, false, 1, -1, false, true)) { }
4482 AstNode
*sel_case
= NULL
;
4483 for (size_t i
= 1; i
< stmt
->children
.size(); i
++)
4485 bool found_match
= false;
4486 log_assert(stmt
->children
.at(i
)->type
== AST_COND
|| stmt
->children
.at(i
)->type
== AST_CONDX
|| stmt
->children
.at(i
)->type
== AST_CONDZ
);
4488 if (stmt
->children
.at(i
)->children
.front()->type
== AST_DEFAULT
) {
4489 sel_case
= stmt
->children
.at(i
)->children
.back();
4493 for (size_t j
= 0; j
+1 < stmt
->children
.at(i
)->children
.size() && !found_match
; j
++)
4495 AstNode
*cond
= stmt
->children
.at(i
)->children
.at(j
)->clone();
4496 cond
->replace_variables(variables
, fcall
);
4498 cond
= new AstNode(AST_EQ
, expr
->clone(), cond
);
4499 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
4501 if (cond
->type
!= AST_CONSTANT
)
4502 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4503 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4505 found_match
= cond
->asBool();
4510 sel_case
= stmt
->children
.at(i
)->children
.back();
4515 block
->children
.erase(block
->children
.begin());
4517 block
->children
.insert(block
->children
.begin(), sel_case
->clone());
4523 if (stmt
->type
== AST_BLOCK
)
4525 block
->children
.erase(block
->children
.begin());
4526 block
->children
.insert(block
->children
.begin(), stmt
->children
.begin(), stmt
->children
.end());
4527 stmt
->children
.clear();
4532 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Unsupported language construct in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4533 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4539 for (auto &it
: backup_scope
)
4540 if (it
.second
== NULL
)
4541 current_scope
.erase(it
.first
);
4543 current_scope
[it
.first
] = it
.second
;
4545 return AstNode::mkconst_bits(variables
.at(str
).val
.bits
, variables
.at(str
).is_signed
);
4548 void AstNode::allocateDefaultEnumValues()
4550 log_assert(type
==AST_ENUM
);
4551 int last_enum_int
= -1;
4552 for (auto node
: children
) {
4553 log_assert(node
->type
==AST_ENUM_ITEM
);
4554 node
->attributes
[ID::enum_base_type
] = mkconst_str(str
);
4555 for (size_t i
= 0; i
< node
->children
.size(); i
++) {
4556 switch (node
->children
[i
]->type
) {
4558 // replace with auto-incremented constant
4559 delete node
->children
[i
];
4560 node
->children
[i
] = AstNode::mkconst_int(++last_enum_int
, true);
4563 // explicit constant (or folded expression)
4564 // TODO: can't extend 'x or 'z item
4565 last_enum_int
= node
->children
[i
]->integer
;
4571 // TODO: range check