2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
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
92 if (got_len
&& len_value
!= 0)
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
;
116 goto unsupported_format
;
121 log_file_error(filename
, location
.first_line
, "System task `%s' called with invalid/unsupported format specifier.\n", str
.c_str());
129 sout
+= node_arg
->bitsAsConst().decode_string();
134 sout
+= stringf("%d", node_arg
->bitsAsConst().as_int());
140 Const val
= node_arg
->bitsAsConst();
142 while (GetSize(val
) % 4 != 0)
143 val
.bits
.push_back(State::S0
);
145 int len
= GetSize(val
) / 4;
146 for (int i
= len
; i
< len_value
; i
++)
147 sout
+= got_zlen
? '0' : ' ';
149 for (int i
= len
-1; i
>= 0; i
--) {
150 Const digit
= val
.extract(4*i
, 4);
151 if (digit
.is_fully_def())
152 sout
+= stringf(cformat
== 'x' ? "%x" : "%X", digit
.as_int());
154 sout
+= cformat
== 'x' ? "x" : "X";
161 sout
+= log_id(current_module
->name
);
166 sout
+= log_id(current_module
->name
);
174 // not a format specifier
182 void AstNode::annotateTypedEnums(AstNode
*template_node
)
185 if (template_node
->attributes
.count(ID::enum_type
)) {
186 //get reference to enum node:
187 std::string enum_type
= template_node
->attributes
[ID::enum_type
]->str
.c_str();
188 // log("enum_type=%s (count=%lu)\n", enum_type.c_str(), current_scope.count(enum_type));
189 // log("current scope:\n");
190 // for (auto &it : current_scope)
191 // log(" %s\n", it.first.c_str());
192 log_assert(current_scope
.count(enum_type
) == 1);
193 AstNode
*enum_node
= current_scope
.at(enum_type
);
194 log_assert(enum_node
->type
== AST_ENUM
);
195 while (enum_node
->simplify(true, false, false, 1, -1, false, true)) { }
196 //get width from 1st enum item:
197 log_assert(enum_node
->children
.size() >= 1);
198 AstNode
*enum_item0
= enum_node
->children
[0];
199 log_assert(enum_item0
->type
== AST_ENUM_ITEM
);
201 if (!enum_item0
->range_valid
)
203 else if (enum_item0
->range_swapped
)
204 width
= enum_item0
->range_right
- enum_item0
->range_left
+ 1;
206 width
= enum_item0
->range_left
- enum_item0
->range_right
+ 1;
207 log_assert(width
> 0);
208 //add declared enum items:
209 for (auto enum_item
: enum_node
->children
){
210 log_assert(enum_item
->type
== AST_ENUM_ITEM
);
213 if (enum_item
->children
.size() == 1){
215 } else if (enum_item
->children
.size() == 2){
216 log_assert(enum_item
->children
[1]->type
== AST_RANGE
);
217 is_signed
= enum_item
->children
[1]->is_signed
;
219 log_error("enum_item children size==%lu, expected 1 or 2 for %s (%s)\n",
220 enum_item
->children
.size(),
221 enum_item
->str
.c_str(), enum_node
->str
.c_str()
224 //start building attribute string
225 std::string enum_item_str
= "\\enum_value_";
226 //get enum item value
227 if(enum_item
->children
[0]->type
!= AST_CONSTANT
){
228 log_error("expected const, got %s for %s (%s)\n",
229 type2str(enum_item
->children
[0]->type
).c_str(),
230 enum_item
->str
.c_str(), enum_node
->str
.c_str()
233 RTLIL::Const val
= enum_item
->children
[0]->bitsAsConst(width
, is_signed
);
234 enum_item_str
.append(val
.as_string());
235 //set attribute for available val to enum item name mappings
236 attributes
[enum_item_str
.c_str()] = mkconst_str(enum_item
->str
);
241 static bool name_has_dot(const std::string
&name
, std::string
&struct_name
)
243 // check if plausible struct member name \sss.mmm
244 std::string::size_type pos
;
245 if (name
.substr(0, 1) == "\\" && (pos
= name
.find('.', 0)) != std::string::npos
) {
246 struct_name
= name
.substr(0, pos
);
252 static AstNode
*make_range(int left
, int right
, bool is_signed
= false)
254 // generate a pre-validated range node for a fixed signal range.
255 auto range
= new AstNode(AST_RANGE
);
256 range
->range_left
= left
;
257 range
->range_right
= right
;
258 range
->range_valid
= true;
259 range
->children
.push_back(AstNode::mkconst_int(left
, true));
260 range
->children
.push_back(AstNode::mkconst_int(right
, true));
261 range
->is_signed
= is_signed
;
265 static int range_width(AstNode
*node
, AstNode
*rnode
)
267 log_assert(rnode
->type
==AST_RANGE
);
268 if (!rnode
->range_valid
) {
269 log_file_error(node
->filename
, node
->location
.first_line
, "Size must be constant in packed struct/union member %s\n", node
->str
.c_str());
272 // note: range swapping has already been checked for
273 return rnode
->range_left
- rnode
->range_right
+ 1;
276 [[noreturn
]] static void struct_array_packing_error(AstNode
*node
)
278 log_file_error(node
->filename
, node
->location
.first_line
, "Unpacked array in packed struct/union member %s\n", node
->str
.c_str());
281 static void save_struct_array_width(AstNode
*node
, int width
)
283 // stash the stride for the array
284 node
->multirange_dimensions
.push_back(width
);
288 static int get_struct_array_width(AstNode
*node
)
290 // the stride for the array, 1 if not an array
291 return (node
->multirange_dimensions
.empty() ? 1 : node
->multirange_dimensions
.back());
295 static int size_packed_struct(AstNode
*snode
, int base_offset
)
297 // Struct members will be laid out in the structure contiguously from left to right.
298 // Union members all have zero offset from the start of the union.
299 // Determine total packed size and assign offsets. Store these in the member node.
300 bool is_union
= (snode
->type
== AST_UNION
);
302 int packed_width
= -1;
303 // examine members from last to first
304 for (auto it
= snode
->children
.rbegin(); it
!= snode
->children
.rend(); ++it
) {
307 if (node
->type
== AST_STRUCT
|| node
->type
== AST_UNION
) {
308 // embedded struct or union
309 width
= size_packed_struct(node
, base_offset
+ offset
);
312 log_assert(node
->type
== AST_STRUCT_ITEM
);
313 if (node
->children
.size() > 0 && node
->children
[0]->type
== AST_RANGE
) {
314 // member width e.g. bit [7:0] a
315 width
= range_width(node
, node
->children
[0]);
316 if (node
->children
.size() == 2) {
317 if (node
->children
[1]->type
== AST_RANGE
) {
318 // unpacked array e.g. bit [63:0] a [0:3]
319 auto rnode
= node
->children
[1];
320 int array_count
= range_width(node
, rnode
);
321 if (array_count
== 1) {
322 // C-type array size e.g. bit [63:0] a [4]
323 array_count
= rnode
->range_left
;
325 save_struct_array_width(node
, width
);
326 width
*= array_count
;
329 // array element must be single bit for a packed array
330 struct_array_packing_error(node
);
333 // range nodes are now redundant
334 for (AstNode
*child
: node
->children
)
336 node
->children
.clear();
338 else if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_MULTIRANGE
) {
339 // packed 2D array, e.g. bit [3:0][63:0] a
340 auto rnode
= node
->children
[0];
341 if (rnode
->children
.size() != 2) {
342 // packed arrays can only be 2D
343 struct_array_packing_error(node
);
345 int array_count
= range_width(node
, rnode
->children
[0]);
346 width
= range_width(node
, rnode
->children
[1]);
347 save_struct_array_width(node
, width
);
348 width
*= array_count
;
349 // range nodes are now redundant
350 for (AstNode
*child
: node
->children
)
352 node
->children
.clear();
354 else if (node
->range_left
< 0) {
355 // 1 bit signal: bit, logic or reg
359 // already resolved and compacted
360 width
= node
->range_left
- node
->range_right
+ 1;
363 node
->range_right
= base_offset
;
364 node
->range_left
= base_offset
+ width
- 1;
367 node
->range_right
= base_offset
+ offset
;
368 node
->range_left
= base_offset
+ offset
+ width
- 1;
370 node
->range_valid
= true;
373 // check that all members have the same size
374 if (packed_width
== -1) {
376 packed_width
= width
;
379 if (packed_width
!= width
) {
381 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
);
389 return (is_union
? packed_width
: offset
);
392 [[noreturn
]] static void struct_op_error(AstNode
*node
)
394 log_file_error(node
->filename
, node
->location
.first_line
, "Unsupported operation for struct/union member %s\n", node
->str
.c_str()+1);
397 static AstNode
*node_int(int ival
)
399 return AstNode::mkconst_int(ival
, true);
402 static AstNode
*multiply_by_const(AstNode
*expr_node
, int stride
)
404 return new AstNode(AST_MUL
, expr_node
, node_int(stride
));
407 static AstNode
*offset_indexed_range(int offset
, int stride
, AstNode
*left_expr
, AstNode
*right_expr
)
409 // adjust the range expressions to add an offset into the struct
410 // and maybe index using an array stride
411 auto left
= left_expr
->clone();
412 auto right
= right_expr
->clone();
414 // newleft = (left + 1) * stride - 1
415 left
= new AstNode(AST_SUB
, multiply_by_const(new AstNode(AST_ADD
, left
, node_int(1)), stride
), node_int(1));
416 // newright = right * stride
417 right
= multiply_by_const(right
, stride
);
421 left
= new AstNode(AST_ADD
, node_int(offset
), left
);
422 right
= new AstNode(AST_ADD
, node_int(offset
), right
);
424 return new AstNode(AST_RANGE
, left
, right
);
427 static AstNode
*make_struct_index_range(AstNode
*node
, AstNode
*rnode
, int stride
, int offset
)
429 // generate a range node to perform either bit or array indexing
430 if (rnode
->children
.size() == 1) {
432 return offset_indexed_range(offset
, stride
, rnode
->children
[0], rnode
->children
[0]);
434 else if (rnode
->children
.size() == 2) {
435 // slice e.g. s.a[i:j]
436 return offset_indexed_range(offset
, stride
, rnode
->children
[0], rnode
->children
[1]);
439 struct_op_error(node
);
443 static AstNode
*slice_range(AstNode
*rnode
, AstNode
*snode
)
445 // apply the bit slice indicated by snode to the range rnode
446 log_assert(rnode
->type
==AST_RANGE
);
447 auto left
= rnode
->children
[0];
448 auto right
= rnode
->children
[1];
449 log_assert(snode
->type
==AST_RANGE
);
450 auto slice_left
= snode
->children
[0];
451 auto slice_right
= snode
->children
[1];
452 auto width
= new AstNode(AST_SUB
, slice_left
->clone(), slice_right
->clone());
453 right
= new AstNode(AST_ADD
, right
->clone(), slice_right
->clone());
454 left
= new AstNode(AST_ADD
, right
->clone(), width
);
455 return new AstNode(AST_RANGE
, left
, right
);
459 AstNode
*AST::make_struct_member_range(AstNode
*node
, AstNode
*member_node
)
461 // Work out the range in the packed array that corresponds to a struct member
462 // taking into account any range operations applicable to the current node
463 // such as array indexing or slicing
464 int range_left
= member_node
->range_left
;
465 int range_right
= member_node
->range_right
;
466 if (node
->children
.empty()) {
467 // no range operations apply, return the whole width
468 return make_range(range_left
, range_right
);
470 int stride
= get_struct_array_width(member_node
);
471 if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
472 // bit or array indexing e.g. s.a[2] or s.a[1:0]
473 return make_struct_index_range(node
, node
->children
[0], stride
, range_right
);
475 else if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_MULTIRANGE
) {
476 // multirange, i.e. bit slice after array index, e.g. s.a[i][p:q]
477 log_assert(stride
> 1);
478 auto mrnode
= node
->children
[0];
479 auto element_range
= make_struct_index_range(node
, mrnode
->children
[0], stride
, range_right
);
480 // then apply bit slice range
481 auto range
= slice_range(element_range
, mrnode
->children
[1]);
482 delete element_range
;
486 struct_op_error(node
);
490 static void add_members_to_scope(AstNode
*snode
, std::string name
)
492 // add all the members in a struct or union to local scope
493 // in case later referenced in assignments
494 log_assert(snode
->type
==AST_STRUCT
|| snode
->type
==AST_UNION
);
495 for (auto *node
: snode
->children
) {
496 if (node
->type
!= AST_STRUCT_ITEM
) {
497 // embedded struct or union
498 add_members_to_scope(node
, name
+ "." + node
->str
);
501 auto member_name
= name
+ "." + node
->str
;
502 current_scope
[member_name
] = node
;
507 static int get_max_offset(AstNode
*node
)
509 // get the width from the MS member in the struct
510 // as members are laid out from left to right in the packed wire
511 log_assert(node
->type
==AST_STRUCT
|| node
->type
==AST_UNION
);
512 while (node
->type
!= AST_STRUCT_ITEM
) {
513 node
= node
->children
[0];
515 return node
->range_left
;
518 static AstNode
*make_packed_struct(AstNode
*template_node
, std::string
&name
)
520 // create a wire for the packed struct
521 auto wnode
= new AstNode(AST_WIRE
);
523 wnode
->is_logic
= true;
524 wnode
->range_valid
= true;
525 wnode
->is_signed
= template_node
->is_signed
;
526 int offset
= get_max_offset(template_node
);
527 auto range
= make_range(offset
, 0);
528 wnode
->children
.push_back(range
);
529 // make sure this node is the one in scope for this name
530 current_scope
[name
] = wnode
;
531 // add all the struct members to scope under the wire's name
532 add_members_to_scope(template_node
, name
);
536 // check if a node or its children contains an assignment to the given variable
537 static bool node_contains_assignment_to(const AstNode
* node
, const AstNode
* var
)
539 if (node
->type
== AST_ASSIGN_EQ
|| node
->type
== AST_ASSIGN_LE
) {
540 // current node is iteslf an assignment
541 log_assert(node
->children
.size() >= 2);
542 const AstNode
* lhs
= node
->children
[0];
543 if (lhs
->type
== AST_IDENTIFIER
&& lhs
->str
== var
->str
)
546 for (const AstNode
* child
: node
->children
) {
547 // if this child shadows the given variable
548 if (child
!= var
&& child
->str
== var
->str
&& child
->type
== AST_WIRE
)
549 break; // skip the remainder of this block/scope
550 // depth-first short circuit
551 if (!node_contains_assignment_to(child
, var
))
557 static std::string
prefix_id(const std::string
&prefix
, const std::string
&str
)
559 log_assert(!prefix
.empty() && (prefix
.front() == '$' || prefix
.front() == '\\'));
560 log_assert(!str
.empty() && (str
.front() == '$' || str
.front() == '\\'));
561 log_assert(prefix
.back() == '.');
562 if (str
.front() == '\\')
563 return prefix
+ str
.substr(1);
567 // convert the AST into a simpler AST that has all parameters substituted by their
568 // values, unrolled for-loops, expanded generate blocks, etc. when this function
569 // is done with an AST it can be converted into RTLIL using genRTLIL().
571 // this function also does all name resolving and sets the id2ast member of all
572 // nodes that link to a different node using names and lexical scoping.
573 bool AstNode::simplify(bool const_fold
, bool at_zero
, bool in_lvalue
, int stage
, int width_hint
, bool sign_hint
, bool in_param
)
575 static int recursion_counter
= 0;
576 static bool deep_recursion_warning
= false;
578 if (recursion_counter
++ == 1000 && deep_recursion_warning
) {
579 log_warning("Deep recursion in AST simplifier.\nDoes this design contain overly long or deeply nested expressions, or excessive recursion?\n");
580 deep_recursion_warning
= false;
583 static bool unevaluated_tern_branch
= false;
585 AstNode
*newNode
= NULL
;
586 bool did_something
= false;
589 log("-------------\n");
590 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);
591 log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
592 int(const_fold
), int(at_zero
), int(in_lvalue
), int(stage
), int(width_hint
), int(sign_hint
), int(in_param
));
593 // dumpAst(NULL, "> ");
598 log_assert(type
== AST_MODULE
|| type
== AST_INTERFACE
);
600 deep_recursion_warning
= true;
601 while (simplify(const_fold
, at_zero
, in_lvalue
, 1, width_hint
, sign_hint
, in_param
)) { }
603 if (!flag_nomem2reg
&& !get_bool_attribute(ID::nomem2reg
))
605 dict
<AstNode
*, pool
<std::string
>> mem2reg_places
;
606 dict
<AstNode
*, uint32_t> mem2reg_candidates
, dummy_proc_flags
;
607 uint32_t flags
= flag_mem2reg
? AstNode::MEM2REG_FL_ALL
: 0;
608 mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, dummy_proc_flags
, flags
);
610 pool
<AstNode
*> mem2reg_set
;
611 for (auto &it
: mem2reg_candidates
)
613 AstNode
*mem
= it
.first
;
614 uint32_t memflags
= it
.second
;
615 bool this_nomeminit
= flag_nomeminit
;
616 log_assert((memflags
& ~0x00ffff00) == 0);
618 if (mem
->get_bool_attribute(ID::nomem2reg
))
621 if (mem
->get_bool_attribute(ID::nomeminit
) || get_bool_attribute(ID::nomeminit
))
622 this_nomeminit
= true;
624 if (memflags
& AstNode::MEM2REG_FL_FORCED
)
625 goto silent_activate
;
627 if (memflags
& AstNode::MEM2REG_FL_EQ2
)
628 goto verbose_activate
;
630 if (memflags
& AstNode::MEM2REG_FL_SET_ASYNC
)
631 goto verbose_activate
;
633 if ((memflags
& AstNode::MEM2REG_FL_SET_INIT
) && (memflags
& AstNode::MEM2REG_FL_SET_ELSE
) && this_nomeminit
)
634 goto verbose_activate
;
636 if (memflags
& AstNode::MEM2REG_FL_CMPLX_LHS
)
637 goto verbose_activate
;
639 if ((memflags
& AstNode::MEM2REG_FL_CONST_LHS
) && !(memflags
& AstNode::MEM2REG_FL_VAR_LHS
))
640 goto verbose_activate
;
642 // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
646 if (mem2reg_set
.count(mem
) == 0) {
647 std::string message
= stringf("Replacing memory %s with list of registers.", mem
->str
.c_str());
648 bool first_element
= true;
649 for (auto &place
: mem2reg_places
[it
.first
]) {
650 message
+= stringf("%s%s", first_element
? " See " : ", ", place
.c_str());
651 first_element
= false;
653 log_warning("%s\n", message
.c_str());
657 // log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
658 mem2reg_set
.insert(mem
);
661 for (auto node
: mem2reg_set
)
663 int mem_width
, mem_size
, addr_bits
;
664 node
->meminfo(mem_width
, mem_size
, addr_bits
);
666 int data_range_left
= node
->children
[0]->range_left
;
667 int data_range_right
= node
->children
[0]->range_right
;
669 if (node
->children
[0]->range_swapped
)
670 std::swap(data_range_left
, data_range_right
);
672 for (int i
= 0; i
< mem_size
; i
++) {
673 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
674 mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
675 reg
->str
= stringf("%s[%d]", node
->str
.c_str(), i
);
677 reg
->is_signed
= node
->is_signed
;
678 for (auto &it
: node
->attributes
)
679 if (it
.first
!= ID::mem2reg
)
680 reg
->attributes
.emplace(it
.first
, it
.second
->clone());
681 reg
->filename
= node
->filename
;
682 reg
->location
= node
->location
;
683 children
.push_back(reg
);
684 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
688 AstNode
*async_block
= NULL
;
689 while (mem2reg_as_needed_pass2(mem2reg_set
, this, NULL
, async_block
)) { }
691 vector
<AstNode
*> delnodes
;
692 mem2reg_remove(mem2reg_set
, delnodes
);
694 for (auto node
: delnodes
)
698 while (simplify(const_fold
, at_zero
, in_lvalue
, 2, width_hint
, sign_hint
, in_param
)) { }
703 current_filename
= filename
;
705 // we do not look inside a task or function
706 // (but as soon as a task or function is instantiated we process the generated AST as usual)
707 if (type
== AST_FUNCTION
|| type
== AST_TASK
) {
712 // deactivate all calls to non-synthesis system tasks
713 // note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
714 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && (str
== "$strobe" || str
== "$monitor" || str
== "$time" ||
715 str
== "$dumpfile" || str
== "$dumpvars" || str
== "$dumpon" || str
== "$dumpoff" || str
== "$dumpall")) {
716 log_file_warning(filename
, location
.first_line
, "Ignoring call to system %s %s.\n", type
== AST_FCALL
? "function" : "task", str
.c_str());
721 if ((type
== AST_TCALL
) && (str
== "$display" || str
== "$write") && (!current_always
|| current_always
->type
!= AST_INITIAL
)) {
722 log_file_warning(filename
, location
.first_line
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
727 // print messages if this a call to $display() or $write()
728 // This code implements only a small subset of Verilog-2005 $display() format specifiers,
729 // but should be good enough for most uses
730 if ((type
== AST_TCALL
) && ((str
== "$display") || (str
== "$write")))
732 int nargs
= GetSize(children
);
734 log_file_error(filename
, location
.first_line
, "System task `%s' got %d arguments, expected >= 1.\n",
735 str
.c_str(), int(children
.size()));
737 // First argument is the format string
738 AstNode
*node_string
= children
[0];
739 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
740 if (node_string
->type
!= AST_CONSTANT
)
741 log_file_error(filename
, location
.first_line
, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str
.c_str());
742 std::string sformat
= node_string
->bitsAsConst().decode_string();
743 std::string sout
= process_format_str(sformat
, 1, stage
, width_hint
, sign_hint
);
744 // Finally, print the message (only include a \n for $display, not for $write)
745 log("%s", sout
.c_str());
746 if (str
== "$display")
752 // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
753 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
)
755 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
))
758 // in certain cases a function must be evaluated constant. this is what in_param controls.
759 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_PREFIX
)
762 std::map
<std::string
, AstNode
*> backup_scope
;
764 // create name resolution entries for all objects with names
765 // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
766 if (type
== AST_MODULE
) {
767 current_scope
.clear();
768 std::set
<std::string
> existing
;
770 label_genblks(existing
, counter
);
771 std::map
<std::string
, AstNode
*> this_wire_scope
;
772 for (size_t i
= 0; i
< children
.size(); i
++) {
773 AstNode
*node
= children
[i
];
775 if (node
->type
== AST_WIRE
) {
776 if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
777 for (auto c
: node
->children
[0]->children
) {
778 if (!c
->is_simple_const_expr()) {
779 if (attributes
.count(ID::dynports
))
780 delete attributes
.at(ID::dynports
);
781 attributes
[ID::dynports
] = AstNode::mkconst_int(1, true);
785 if (this_wire_scope
.count(node
->str
) > 0) {
786 AstNode
*first_node
= this_wire_scope
[node
->str
];
787 if (first_node
->is_input
&& node
->is_reg
)
788 goto wires_are_incompatible
;
789 if (!node
->is_input
&& !node
->is_output
&& node
->is_reg
&& node
->children
.size() == 0)
790 goto wires_are_compatible
;
791 if (first_node
->children
.size() == 0 && node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
792 AstNode
*r
= node
->children
[0];
793 if (r
->range_valid
&& r
->range_left
== 0 && r
->range_right
== 0) {
795 node
->children
.pop_back();
798 if (first_node
->children
.size() != node
->children
.size())
799 goto wires_are_incompatible
;
800 for (size_t j
= 0; j
< node
->children
.size(); j
++) {
801 AstNode
*n1
= first_node
->children
[j
], *n2
= node
->children
[j
];
802 if (n1
->type
== AST_RANGE
&& n2
->type
== AST_RANGE
&& n1
->range_valid
&& n2
->range_valid
) {
803 if (n1
->range_left
!= n2
->range_left
)
804 goto wires_are_incompatible
;
805 if (n1
->range_right
!= n2
->range_right
)
806 goto wires_are_incompatible
;
807 } else if (*n1
!= *n2
)
808 goto wires_are_incompatible
;
810 if (first_node
->range_left
!= node
->range_left
)
811 goto wires_are_incompatible
;
812 if (first_node
->range_right
!= node
->range_right
)
813 goto wires_are_incompatible
;
814 if (first_node
->port_id
== 0 && (node
->is_input
|| node
->is_output
))
815 goto wires_are_incompatible
;
816 wires_are_compatible
:
818 first_node
->is_input
= true;
820 first_node
->is_output
= true;
822 first_node
->is_reg
= true;
824 first_node
->is_logic
= true;
826 first_node
->is_signed
= true;
827 for (auto &it
: node
->attributes
) {
828 if (first_node
->attributes
.count(it
.first
) > 0)
829 delete first_node
->attributes
[it
.first
];
830 first_node
->attributes
[it
.first
] = it
.second
->clone();
832 children
.erase(children
.begin()+(i
--));
833 did_something
= true;
836 wires_are_incompatible
:
838 log_file_error(filename
, location
.first_line
, "Incompatible re-declaration of wire %s.\n", node
->str
.c_str());
841 this_wire_scope
[node
->str
] = node
;
843 // these nodes appear at the top level in a module and can define names
844 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
845 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
|| node
->type
== AST_CELL
||
846 node
->type
== AST_TYPEDEF
) {
847 backup_scope
[node
->str
] = current_scope
[node
->str
];
848 current_scope
[node
->str
] = node
;
850 if (node
->type
== AST_ENUM
) {
851 current_scope
[node
->str
] = node
;
852 for (auto enode
: node
->children
) {
853 log_assert(enode
->type
==AST_ENUM_ITEM
);
854 if (current_scope
.count(enode
->str
) == 0)
855 current_scope
[enode
->str
] = enode
;
857 log_file_error(filename
, location
.first_line
, "enum item %s already exists\n", enode
->str
.c_str());
861 for (size_t i
= 0; i
< children
.size(); i
++) {
862 AstNode
*node
= children
[i
];
863 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
)
864 while (node
->simplify(true, false, false, 1, -1, false, node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
))
865 did_something
= true;
866 if (node
->type
== AST_ENUM
) {
867 for (auto enode
: node
->children
){
868 log_assert(enode
->type
==AST_ENUM_ITEM
);
869 while (node
->simplify(true, false, false, 1, -1, false, in_param
))
870 did_something
= true;
876 // create name resolution entries for all objects with names
877 if (type
== AST_PACKAGE
) {
878 //add names to package scope
879 for (size_t i
= 0; i
< children
.size(); i
++) {
880 AstNode
*node
= children
[i
];
881 // these nodes appear at the top level in a package and can define names
882 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_TYPEDEF
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
) {
883 current_scope
[node
->str
] = node
;
885 if (node
->type
== AST_ENUM
) {
886 current_scope
[node
->str
] = node
;
887 for (auto enode
: node
->children
) {
888 log_assert(enode
->type
==AST_ENUM_ITEM
);
889 if (current_scope
.count(enode
->str
) == 0)
890 current_scope
[enode
->str
] = enode
;
892 log_file_error(filename
, location
.first_line
, "enum item %s already exists in package\n", enode
->str
.c_str());
899 auto backup_current_block
= current_block
;
900 auto backup_current_block_child
= current_block_child
;
901 auto backup_current_top_block
= current_top_block
;
902 auto backup_current_always
= current_always
;
903 auto backup_current_always_clocked
= current_always_clocked
;
905 if (type
== AST_ALWAYS
|| type
== AST_INITIAL
)
907 if (current_always
!= nullptr)
908 log_file_error(filename
, location
.first_line
, "Invalid nesting of always blocks and/or initializations.\n");
910 current_always
= this;
911 current_always_clocked
= false;
913 if (type
== AST_ALWAYS
)
914 for (auto child
: children
) {
915 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
916 current_always_clocked
= true;
917 if (child
->type
== AST_EDGE
&& GetSize(child
->children
) == 1 &&
918 child
->children
[0]->type
== AST_IDENTIFIER
&& child
->children
[0]->str
== "\\$global_clock")
919 current_always_clocked
= true;
923 if (type
== AST_ARGUMENT
)
925 if (children
.size() == 1 && children
[0]->type
== AST_CONSTANT
)
927 // HACK: For port bindings using unbased unsized literals, mark them
928 // signed so they sign-extend. The hierarchy will still incorrectly
929 // generate a warning complaining about resizing the expression.
930 // This also doesn't handle the complex of something like a ternary
931 // expression bound to a port, where the actual size of the port is
932 // needed to resolve the expression correctly.
933 AstNode
*arg
= children
[0];
935 arg
->is_signed
= true;
939 int backup_width_hint
= width_hint
;
940 bool backup_sign_hint
= sign_hint
;
942 bool detect_width_simple
= false;
943 bool child_0_is_self_determined
= false;
944 bool child_1_is_self_determined
= false;
945 bool child_2_is_self_determined
= false;
946 bool children_are_self_determined
= false;
947 bool reset_width_after_children
= false;
954 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, true, stage
, -1, false, in_param
) == true)
955 did_something
= true;
956 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
) == true)
957 did_something
= true;
958 children
[0]->detectSignWidth(backup_width_hint
, backup_sign_hint
);
959 children
[1]->detectSignWidth(width_hint
, sign_hint
);
960 width_hint
= max(width_hint
, backup_width_hint
);
961 child_0_is_self_determined
= true;
962 // test only once, before optimizations and memory mappings but after assignment LHS was mapped to an identifier
963 if (children
[0]->id2ast
&& !children
[0]->was_checked
) {
964 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->id2ast
->is_logic
)
965 children
[0]->id2ast
->is_reg
= true; // if logic type is used in a block asignment
966 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && !children
[0]->id2ast
->is_reg
)
967 log_warning("wire '%s' is assigned in a block at %s.\n", children
[0]->str
.c_str(), loc_string().c_str());
968 if (type
== AST_ASSIGN
&& children
[0]->id2ast
->is_reg
) {
969 bool is_rand_reg
= false;
970 if (children
[1]->type
== AST_FCALL
) {
971 if (children
[1]->str
== "\\$anyconst")
973 if (children
[1]->str
== "\\$anyseq")
975 if (children
[1]->str
== "\\$allconst")
977 if (children
[1]->str
== "\\$allseq")
981 log_warning("reg '%s' is assigned in a continuous assignment at %s.\n", children
[0]->str
.c_str(), loc_string().c_str());
983 children
[0]->was_checked
= true;
990 for (auto *node
: children
) {
991 // resolve any ranges
992 while (!node
->basic_prep
&& node
->simplify(true, false, false, stage
, -1, false, false)) {
993 did_something
= true;
996 // determine member offsets and widths
997 size_packed_struct(this, 0);
999 // instance rather than just a type in a typedef or outer struct?
1000 if (!str
.empty() && str
[0] == '\\') {
1001 // instance so add a wire for the packed structure
1002 auto wnode
= make_packed_struct(this, str
);
1003 log_assert(current_ast_mod
);
1004 current_ast_mod
->children
.push_back(wnode
);
1010 case AST_STRUCT_ITEM
:
1014 //log("\nENUM %s: %d child %d\n", str.c_str(), basic_prep, children[0]->basic_prep);
1016 for (auto item_node
: children
) {
1017 while (!item_node
->basic_prep
&& item_node
->simplify(false, false, false, stage
, -1, false, in_param
))
1018 did_something
= true;
1020 // allocate values (called more than once)
1021 allocateDefaultEnumValues();
1026 case AST_LOCALPARAM
:
1027 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, true) == true)
1028 did_something
= true;
1029 children
[0]->detectSignWidth(width_hint
, sign_hint
);
1030 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
1031 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, true) == true)
1032 did_something
= true;
1033 if (!children
[1]->range_valid
)
1034 log_file_error(filename
, location
.first_line
, "Non-constant width range on parameter decl.\n");
1035 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
1039 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, in_param
))
1040 did_something
= true;
1041 children
[0]->detectSignWidth(width_hint
, sign_hint
);
1042 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
1043 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
))
1044 did_something
= true;
1045 if (!children
[1]->range_valid
)
1046 log_file_error(filename
, location
.first_line
, "Non-constant width range on enum item decl.\n");
1047 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
1053 case AST_TO_UNSIGNED
:
1058 case AST_REDUCE_AND
:
1060 case AST_REDUCE_XOR
:
1061 case AST_REDUCE_XNOR
:
1062 case AST_REDUCE_BOOL
:
1063 detect_width_simple
= true;
1064 children_are_self_determined
= true;
1079 detect_width_simple
= true;
1082 case AST_SHIFT_LEFT
:
1083 case AST_SHIFT_RIGHT
:
1084 case AST_SHIFT_SLEFT
:
1085 case AST_SHIFT_SRIGHT
:
1087 detect_width_simple
= true;
1088 child_1_is_self_determined
= true;
1101 for (auto child
: children
) {
1102 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
1103 did_something
= true;
1104 child
->detectSignWidthWorker(width_hint
, sign_hint
);
1106 reset_width_after_children
= true;
1112 detect_width_simple
= true;
1113 children_are_self_determined
= true;
1117 child_0_is_self_determined
= true;
1121 detect_width_simple
= true;
1122 children_are_self_determined
= true;
1127 children_are_self_determined
= true;
1135 if (detect_width_simple
&& width_hint
< 0) {
1136 if (type
== AST_REPLICATE
)
1137 while (children
[0]->simplify(true, false, in_lvalue
, stage
, -1, false, true) == true)
1138 did_something
= true;
1139 for (auto child
: children
)
1140 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
1141 did_something
= true;
1142 detectSignWidth(width_hint
, sign_hint
);
1145 if (type
== AST_FCALL
&& str
== "\\$past")
1146 detectSignWidth(width_hint
, sign_hint
);
1148 if (type
== AST_TERNARY
) {
1149 if (width_hint
< 0) {
1150 while (!children
[0]->basic_prep
&& children
[0]->simplify(true, false, in_lvalue
, stage
, -1, false, in_param
))
1151 did_something
= true;
1153 bool backup_unevaluated_tern_branch
= unevaluated_tern_branch
;
1154 AstNode
*chosen
= get_tern_choice().first
;
1156 unevaluated_tern_branch
= backup_unevaluated_tern_branch
|| chosen
== children
[2];
1157 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
))
1158 did_something
= true;
1160 unevaluated_tern_branch
= backup_unevaluated_tern_branch
|| chosen
== children
[1];
1161 while (!children
[2]->basic_prep
&& children
[2]->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
))
1162 did_something
= true;
1164 unevaluated_tern_branch
= backup_unevaluated_tern_branch
;
1165 detectSignWidth(width_hint
, sign_hint
);
1167 int width_hint_left
, width_hint_right
;
1168 bool sign_hint_left
, sign_hint_right
;
1169 bool found_real_left
, found_real_right
;
1170 children
[1]->detectSignWidth(width_hint_left
, sign_hint_left
, &found_real_left
);
1171 children
[2]->detectSignWidth(width_hint_right
, sign_hint_right
, &found_real_right
);
1172 if (found_real_left
|| found_real_right
) {
1173 child_1_is_self_determined
= true;
1174 child_2_is_self_determined
= true;
1178 if (type
== AST_CONDX
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
1179 for (auto &bit
: children
.at(0)->bits
)
1180 if (bit
== State::Sz
|| bit
== State::Sx
)
1184 if (type
== AST_CONDZ
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
1185 for (auto &bit
: children
.at(0)->bits
)
1186 if (bit
== State::Sz
)
1190 if (const_fold
&& type
== AST_CASE
)
1194 detectSignWidth(width_hint
, sign_hint
);
1195 while (children
[0]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
1196 if (children
[0]->type
== AST_CONSTANT
&& children
[0]->bits_only_01()) {
1197 RTLIL::Const case_expr
= children
[0]->bitsAsConst(width_hint
, sign_hint
);
1198 std::vector
<AstNode
*> new_children
;
1199 new_children
.push_back(children
[0]);
1200 for (int i
= 1; i
< GetSize(children
); i
++) {
1201 AstNode
*child
= children
[i
];
1202 log_assert(child
->type
== AST_COND
|| child
->type
== AST_CONDX
|| child
->type
== AST_CONDZ
);
1203 for (auto v
: child
->children
) {
1204 if (v
->type
== AST_DEFAULT
)
1205 goto keep_const_cond
;
1206 if (v
->type
== AST_BLOCK
)
1208 while (v
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
1209 if (v
->type
== AST_CONSTANT
&& v
->bits_only_01()) {
1210 RTLIL::Const case_item_expr
= v
->bitsAsConst(width_hint
, sign_hint
);
1211 RTLIL::Const match
= const_eq(case_expr
, case_item_expr
, sign_hint
, sign_hint
, 1);
1212 log_assert(match
.bits
.size() == 1);
1213 if (match
.bits
.front() == RTLIL::State::S1
) {
1214 while (i
+1 < GetSize(children
))
1215 delete children
[++i
];
1216 goto keep_const_cond
;
1220 goto keep_const_cond
;
1224 new_children
.push_back(child
);
1228 new_children
.swap(children
);
1232 dict
<std::string
, pool
<int>> backup_memwr_visible
;
1233 dict
<std::string
, pool
<int>> final_memwr_visible
;
1235 if (type
== AST_CASE
&& stage
== 2) {
1236 backup_memwr_visible
= current_memwr_visible
;
1237 final_memwr_visible
= current_memwr_visible
;
1240 // simplify all children first
1241 // (iterate by index as e.g. auto wires can add new children in the process)
1242 for (size_t i
= 0; i
< children
.size(); i
++) {
1243 bool did_something_here
= true;
1244 bool backup_flag_autowire
= flag_autowire
;
1245 bool backup_unevaluated_tern_branch
= unevaluated_tern_branch
;
1246 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && i
>= 3)
1248 if ((type
== AST_GENIF
|| type
== AST_GENCASE
) && i
>= 1)
1250 if (type
== AST_GENBLOCK
)
1252 if (type
== AST_BLOCK
&& !str
.empty())
1254 if (type
== AST_PREFIX
&& i
>= 1)
1256 if (type
== AST_DEFPARAM
&& i
== 0)
1257 flag_autowire
= true;
1258 if (type
== AST_TERNARY
&& i
> 0 && !unevaluated_tern_branch
) {
1259 AstNode
*chosen
= get_tern_choice().first
;
1260 unevaluated_tern_branch
= chosen
&& chosen
!= children
[i
];
1262 while (did_something_here
&& i
< children
.size()) {
1263 bool const_fold_here
= const_fold
, in_lvalue_here
= in_lvalue
;
1264 int width_hint_here
= width_hint
;
1265 bool sign_hint_here
= sign_hint
;
1266 bool in_param_here
= in_param
;
1267 if (i
== 0 && (type
== AST_REPLICATE
|| type
== AST_WIRE
))
1268 const_fold_here
= true, in_param_here
= true;
1269 if (i
== 0 && (type
== AST_GENIF
|| type
== AST_GENCASE
))
1270 in_param_here
= true;
1271 if (i
== 1 && (type
== AST_FOR
|| type
== AST_GENFOR
))
1272 in_param_here
= true;
1273 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
)
1274 const_fold_here
= true;
1275 if (i
== 0 && (type
== AST_ASSIGN
|| type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
))
1276 in_lvalue_here
= true;
1277 if (type
== AST_BLOCK
) {
1278 current_block
= this;
1279 current_block_child
= children
[i
];
1281 if ((type
== AST_ALWAYS
|| type
== AST_INITIAL
) && children
[i
]->type
== AST_BLOCK
)
1282 current_top_block
= children
[i
];
1283 if (i
== 0 && child_0_is_self_determined
)
1284 width_hint_here
= -1, sign_hint_here
= false;
1285 if (i
== 1 && child_1_is_self_determined
)
1286 width_hint_here
= -1, sign_hint_here
= false;
1287 if (i
== 2 && child_2_is_self_determined
)
1288 width_hint_here
= -1, sign_hint_here
= false;
1289 if (children_are_self_determined
)
1290 width_hint_here
= -1, sign_hint_here
= false;
1291 did_something_here
= children
[i
]->simplify(const_fold_here
, at_zero
, in_lvalue_here
, stage
, width_hint_here
, sign_hint_here
, in_param_here
);
1292 if (did_something_here
)
1293 did_something
= true;
1295 if (stage
== 2 && children
[i
]->type
== AST_INITIAL
&& current_ast_mod
!= this) {
1296 current_ast_mod
->children
.push_back(children
[i
]);
1297 children
.erase(children
.begin() + (i
--));
1298 did_something
= true;
1300 flag_autowire
= backup_flag_autowire
;
1301 unevaluated_tern_branch
= backup_unevaluated_tern_branch
;
1302 if (stage
== 2 && type
== AST_CASE
) {
1303 for (auto &x
: current_memwr_visible
) {
1304 for (int y
: x
.second
)
1305 final_memwr_visible
[x
.first
].insert(y
);
1307 current_memwr_visible
= backup_memwr_visible
;
1310 for (auto &attr
: attributes
) {
1311 while (attr
.second
->simplify(true, false, false, stage
, -1, false, true))
1312 did_something
= true;
1314 if (type
== AST_CASE
&& stage
== 2) {
1315 current_memwr_visible
= final_memwr_visible
;
1317 if (type
== AST_ALWAYS
&& stage
== 2) {
1318 current_memwr_visible
.clear();
1319 current_memwr_count
.clear();
1322 if (reset_width_after_children
) {
1323 width_hint
= backup_width_hint
;
1324 sign_hint
= backup_sign_hint
;
1326 detectSignWidth(width_hint
, sign_hint
);
1329 current_block
= backup_current_block
;
1330 current_block_child
= backup_current_block_child
;
1331 current_top_block
= backup_current_top_block
;
1332 current_always
= backup_current_always
;
1333 current_always_clocked
= backup_current_always_clocked
;
1335 for (auto it
= backup_scope
.begin(); it
!= backup_scope
.end(); it
++) {
1336 if (it
->second
== NULL
)
1337 current_scope
.erase(it
->first
);
1339 current_scope
[it
->first
] = it
->second
;
1342 current_filename
= filename
;
1344 if (type
== AST_MODULE
)
1345 current_scope
.clear();
1347 // convert defparam nodes to cell parameters
1348 if (type
== AST_DEFPARAM
&& !children
.empty())
1350 if (children
[0]->type
!= AST_IDENTIFIER
)
1351 log_file_error(filename
, location
.first_line
, "Module name in defparam contains non-constant expressions!\n");
1353 string modname
, paramname
= children
[0]->str
;
1355 size_t pos
= paramname
.rfind('.');
1357 while (pos
!= 0 && pos
!= std::string::npos
)
1359 modname
= paramname
.substr(0, pos
);
1361 if (current_scope
.count(modname
))
1364 pos
= paramname
.rfind('.', pos
- 1);
1367 if (pos
== std::string::npos
)
1368 log_file_error(filename
, location
.first_line
, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname
).c_str());
1370 paramname
= "\\" + paramname
.substr(pos
+1);
1372 if (current_scope
.at(modname
)->type
!= AST_CELL
)
1373 log_file_error(filename
, location
.first_line
, "Defparam argument `%s . %s` does not match a cell!\n",
1374 RTLIL::unescape_id(modname
).c_str(), RTLIL::unescape_id(paramname
).c_str());
1376 AstNode
*paraset
= new AstNode(AST_PARASET
, children
[1]->clone(), GetSize(children
) > 2 ? children
[2]->clone() : NULL
);
1377 paraset
->str
= paramname
;
1379 AstNode
*cell
= current_scope
.at(modname
);
1380 cell
->children
.insert(cell
->children
.begin() + 1, paraset
);
1385 if (type
== AST_TYPEDEF
) {
1386 log_assert(children
.size() == 1);
1387 auto type_node
= children
[0];
1388 log_assert(type_node
->type
== AST_WIRE
|| type_node
->type
== AST_MEMORY
|| type_node
->type
== AST_STRUCT
|| type_node
->type
== AST_UNION
);
1389 while (type_node
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {
1390 did_something
= true;
1392 log_assert(!type_node
->is_custom_type
);
1395 // resolve types of wires
1396 if (type
== AST_WIRE
|| type
== AST_MEMORY
) {
1397 if (is_custom_type
) {
1398 log_assert(children
.size() >= 1);
1399 log_assert(children
[0]->type
== AST_WIRETYPE
);
1400 auto type_name
= children
[0]->str
;
1401 if (!current_scope
.count(type_name
)) {
1402 log_file_error(filename
, location
.first_line
, "Unknown identifier `%s' used as type name\n", type_name
.c_str());
1404 AstNode
*resolved_type_node
= current_scope
.at(type_name
);
1405 if (resolved_type_node
->type
!= AST_TYPEDEF
)
1406 log_file_error(filename
, location
.first_line
, "`%s' does not name a type\n", type_name
.c_str());
1407 log_assert(resolved_type_node
->children
.size() == 1);
1408 AstNode
*template_node
= resolved_type_node
->children
[0];
1410 // Ensure typedef itself is fully simplified
1411 while (template_node
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
1413 if (template_node
->type
== AST_STRUCT
|| template_node
->type
== AST_UNION
) {
1414 // replace with wire representing the packed structure
1415 newNode
= make_packed_struct(template_node
, str
);
1416 // add original input/output attribute to resolved wire
1417 newNode
->is_input
= this->is_input
;
1418 newNode
->is_output
= this->is_output
;
1419 current_scope
[str
] = this;
1423 // Remove type reference
1425 children
.erase(children
.begin());
1427 if (type
== AST_WIRE
)
1428 type
= template_node
->type
;
1429 is_reg
= template_node
->is_reg
;
1430 is_logic
= template_node
->is_logic
;
1431 is_signed
= template_node
->is_signed
;
1432 is_string
= template_node
->is_string
;
1433 is_custom_type
= template_node
->is_custom_type
;
1435 range_valid
= template_node
->range_valid
;
1436 range_swapped
= template_node
->range_swapped
;
1437 range_left
= template_node
->range_left
;
1438 range_right
= template_node
->range_right
;
1440 attributes
[ID::wiretype
] = mkconst_str(resolved_type_node
->str
);
1442 // if an enum then add attributes to support simulator tracing
1443 annotateTypedEnums(template_node
);
1445 // Insert clones children from template at beginning
1446 for (int i
= 0; i
< GetSize(template_node
->children
); i
++)
1447 children
.insert(children
.begin() + i
, template_node
->children
[i
]->clone());
1449 if (type
== AST_MEMORY
&& GetSize(children
) == 1) {
1450 // Single-bit memories must have [0:0] range
1451 AstNode
*rng
= make_range(0, 0);
1452 children
.insert(children
.begin(), rng
);
1454 did_something
= true;
1456 log_assert(!is_custom_type
);
1459 // resolve types of parameters
1460 if (type
== AST_LOCALPARAM
|| type
== AST_PARAMETER
) {
1461 if (is_custom_type
) {
1462 log_assert(children
.size() == 2);
1463 log_assert(children
[1]->type
== AST_WIRETYPE
);
1464 if (!current_scope
.count(children
[1]->str
))
1465 log_file_error(filename
, location
.first_line
, "Unknown identifier `%s' used as type name\n", children
[1]->str
.c_str());
1466 AstNode
*resolved_type_node
= current_scope
.at(children
[1]->str
);
1467 if (resolved_type_node
->type
!= AST_TYPEDEF
)
1468 log_file_error(filename
, location
.first_line
, "`%s' does not name a type\n", children
[1]->str
.c_str());
1469 log_assert(resolved_type_node
->children
.size() == 1);
1470 AstNode
*template_node
= resolved_type_node
->children
[0];
1472 children
.pop_back();
1474 // Ensure typedef itself is fully simplified
1475 while(template_node
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
1477 if (template_node
->type
== AST_MEMORY
)
1478 log_file_error(filename
, location
.first_line
, "unpacked array type `%s' cannot be used for a parameter\n", children
[1]->str
.c_str());
1479 is_signed
= template_node
->is_signed
;
1480 is_string
= template_node
->is_string
;
1481 is_custom_type
= template_node
->is_custom_type
;
1483 range_valid
= template_node
->range_valid
;
1484 range_swapped
= template_node
->range_swapped
;
1485 range_left
= template_node
->range_left
;
1486 range_right
= template_node
->range_right
;
1487 attributes
[ID::wiretype
] = mkconst_str(resolved_type_node
->str
);
1488 for (auto template_child
: template_node
->children
)
1489 children
.push_back(template_child
->clone());
1490 did_something
= true;
1492 log_assert(!is_custom_type
);
1495 // resolve constant prefixes
1496 if (type
== AST_PREFIX
) {
1497 if (children
[0]->type
!= AST_CONSTANT
) {
1498 // dumpAst(NULL, "> ");
1499 log_file_error(filename
, location
.first_line
, "Index in generate block prefix syntax is not constant!\n");
1501 if (children
[1]->type
== AST_PREFIX
)
1502 children
[1]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
);
1503 log_assert(children
[1]->type
== AST_IDENTIFIER
);
1504 newNode
= children
[1]->clone();
1505 const char *second_part
= children
[1]->str
.c_str();
1506 if (second_part
[0] == '\\')
1508 newNode
->str
= stringf("%s[%d].%s", str
.c_str(), children
[0]->integer
, second_part
);
1512 // evaluate TO_BITS nodes
1513 if (type
== AST_TO_BITS
) {
1514 if (children
[0]->type
!= AST_CONSTANT
)
1515 log_file_error(filename
, location
.first_line
, "Left operand of to_bits expression is not constant!\n");
1516 if (children
[1]->type
!= AST_CONSTANT
)
1517 log_file_error(filename
, location
.first_line
, "Right operand of to_bits expression is not constant!\n");
1518 RTLIL::Const new_value
= children
[1]->bitsAsConst(children
[0]->bitsAsConst().as_int(), children
[1]->is_signed
);
1519 newNode
= mkconst_bits(new_value
.bits
, children
[1]->is_signed
);
1523 // annotate constant ranges
1524 if (type
== AST_RANGE
) {
1525 bool old_range_valid
= range_valid
;
1526 range_valid
= false;
1527 range_swapped
= false;
1530 log_assert(children
.size() >= 1);
1531 if (children
[0]->type
== AST_CONSTANT
) {
1533 range_left
= children
[0]->integer
;
1534 if (children
.size() == 1)
1535 range_right
= range_left
;
1537 if (children
.size() >= 2) {
1538 if (children
[1]->type
== AST_CONSTANT
)
1539 range_right
= children
[1]->integer
;
1541 range_valid
= false;
1543 if (old_range_valid
!= range_valid
)
1544 did_something
= true;
1545 if (range_valid
&& range_right
> range_left
) {
1546 int tmp
= range_right
;
1547 range_right
= range_left
;
1549 range_swapped
= true;
1553 // annotate wires with their ranges
1554 if (type
== AST_WIRE
) {
1555 if (children
.size() > 0) {
1556 if (children
[0]->range_valid
) {
1558 did_something
= true;
1560 range_swapped
= children
[0]->range_swapped
;
1561 range_left
= children
[0]->range_left
;
1562 range_right
= children
[0]->range_right
;
1563 bool force_upto
= false, force_downto
= false;
1564 if (attributes
.count(ID::force_upto
)) {
1565 AstNode
*val
= attributes
[ID::force_upto
];
1566 if (val
->type
!= AST_CONSTANT
)
1567 log_file_error(filename
, location
.first_line
, "Attribute `force_upto' with non-constant value!\n");
1568 force_upto
= val
->asAttrConst().as_bool();
1570 if (attributes
.count(ID::force_downto
)) {
1571 AstNode
*val
= attributes
[ID::force_downto
];
1572 if (val
->type
!= AST_CONSTANT
)
1573 log_file_error(filename
, location
.first_line
, "Attribute `force_downto' with non-constant value!\n");
1574 force_downto
= val
->asAttrConst().as_bool();
1576 if (force_upto
&& force_downto
)
1577 log_file_error(filename
, location
.first_line
, "Attributes `force_downto' and `force_upto' cannot be both set!\n");
1578 if ((force_upto
&& !range_swapped
) || (force_downto
&& range_swapped
)) {
1579 std::swap(range_left
, range_right
);
1580 range_swapped
= force_upto
;
1585 did_something
= true;
1587 range_swapped
= false;
1593 // resolve multiranges on memory decl
1594 if (type
== AST_MEMORY
&& children
.size() > 1 && children
[1]->type
== AST_MULTIRANGE
)
1597 multirange_dimensions
.clear();
1598 multirange_swapped
.clear();
1599 for (auto range
: children
[1]->children
) {
1600 if (!range
->range_valid
)
1601 log_file_error(filename
, location
.first_line
, "Non-constant range on memory decl.\n");
1602 multirange_dimensions
.push_back(min(range
->range_left
, range
->range_right
));
1603 multirange_dimensions
.push_back(max(range
->range_left
, range
->range_right
) - min(range
->range_left
, range
->range_right
) + 1);
1604 multirange_swapped
.push_back(range
->range_swapped
);
1605 total_size
*= multirange_dimensions
.back();
1608 children
[1] = new AstNode(AST_RANGE
, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size
-1, true));
1609 did_something
= true;
1612 // resolve multiranges on memory access
1613 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
&& children
.size() > 0 && children
[0]->type
== AST_MULTIRANGE
)
1615 AstNode
*index_expr
= nullptr;
1617 integer
= children
[0]->children
.size(); // save original number of dimensions for $size() etc.
1618 for (int i
= 0; 2*i
< GetSize(id2ast
->multirange_dimensions
); i
++)
1620 if (GetSize(children
[0]->children
) <= i
)
1621 log_file_error(filename
, location
.first_line
, "Insufficient number of array indices for %s.\n", log_id(str
));
1623 AstNode
*new_index_expr
= children
[0]->children
[i
]->children
.at(0)->clone();
1625 if (id2ast
->multirange_dimensions
[2*i
])
1626 new_index_expr
= new AstNode(AST_SUB
, new_index_expr
, AstNode::mkconst_int(id2ast
->multirange_dimensions
[2*i
], true));
1629 index_expr
= new_index_expr
;
1631 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
);
1634 for (int i
= GetSize(id2ast
->multirange_dimensions
)/2; i
< GetSize(children
[0]->children
); i
++)
1635 children
.push_back(children
[0]->children
[i
]->clone());
1638 if (index_expr
== nullptr)
1639 children
.erase(children
.begin());
1641 children
[0] = new AstNode(AST_RANGE
, index_expr
);
1643 did_something
= true;
1646 // trim/extend parameters
1647 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_ENUM_ITEM
) {
1648 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
1649 if (!children
[1]->range_valid
)
1650 log_file_error(filename
, location
.first_line
, "Non-constant width range on parameter decl.\n");
1651 int width
= std::abs(children
[1]->range_left
- children
[1]->range_right
) + 1;
1652 if (children
[0]->type
== AST_REALVALUE
) {
1653 RTLIL::Const constvalue
= children
[0]->realAsConst(width
);
1654 log_file_warning(filename
, location
.first_line
, "converting real value %e to binary %s.\n",
1655 children
[0]->realvalue
, log_signal(constvalue
));
1657 children
[0] = mkconst_bits(constvalue
.bits
, sign_hint
);
1658 did_something
= true;
1660 if (children
[0]->type
== AST_CONSTANT
) {
1661 if (width
!= int(children
[0]->bits
.size())) {
1662 RTLIL::SigSpec
sig(children
[0]->bits
);
1663 sig
.extend_u0(width
, children
[0]->is_signed
);
1664 AstNode
*old_child_0
= children
[0];
1665 children
[0] = mkconst_bits(sig
.as_const().bits
, is_signed
);
1668 children
[0]->is_signed
= is_signed
;
1671 range_swapped
= children
[1]->range_swapped
;
1672 range_left
= children
[1]->range_left
;
1673 range_right
= children
[1]->range_right
;
1675 if (children
.size() > 1 && children
[1]->type
== AST_REALVALUE
&& children
[0]->type
== AST_CONSTANT
) {
1676 double as_realvalue
= children
[0]->asReal(sign_hint
);
1678 children
[0] = new AstNode(AST_REALVALUE
);
1679 children
[0]->realvalue
= as_realvalue
;
1680 did_something
= true;
1684 if (type
== AST_IDENTIFIER
&& !basic_prep
) {
1685 // check if a plausible struct member sss.mmmm
1687 if (name_has_dot(str
, sname
)) {
1688 if (current_scope
.count(str
) > 0) {
1689 auto item_node
= current_scope
[str
];
1690 if (item_node
->type
== AST_STRUCT_ITEM
) {
1691 // structure member, rewrite this node to reference the packed struct wire
1692 auto range
= make_struct_member_range(this, item_node
);
1693 newNode
= new AstNode(AST_IDENTIFIER
, range
);
1694 newNode
->str
= sname
;
1695 newNode
->basic_prep
= true;
1696 if (item_node
->is_signed
)
1697 newNode
= new AstNode(AST_TO_SIGNED
, newNode
);
1703 // annotate identifiers using scope resolution and create auto-wires as needed
1704 if (type
== AST_IDENTIFIER
) {
1705 if (current_scope
.count(str
) == 0) {
1706 AstNode
*current_scope_ast
= (current_ast_mod
== nullptr) ? current_ast
: current_ast_mod
;
1707 str
= try_pop_module_prefix();
1708 for (auto node
: current_scope_ast
->children
) {
1709 //log("looking at mod scope child %s\n", type2str(node->type).c_str());
1710 switch (node
->type
) {
1712 case AST_LOCALPARAM
:
1719 case AST_DPI_FUNCTION
:
1720 //log("found child %s, %s\n", type2str(node->type).c_str(), node->str.c_str());
1721 if (str
== node
->str
) {
1722 //log("add %s, type %s to scope\n", str.c_str(), type2str(node->type).c_str());
1723 current_scope
[node
->str
] = node
;
1727 current_scope
[node
->str
] = node
;
1728 for (auto enum_node
: node
->children
) {
1729 log_assert(enum_node
->type
==AST_ENUM_ITEM
);
1730 if (str
== enum_node
->str
) {
1731 //log("\nadding enum item %s to scope\n", str.c_str());
1732 current_scope
[str
] = enum_node
;
1741 if (current_scope
.count(str
) == 0) {
1742 if (current_ast_mod
== nullptr) {
1743 log_file_error(filename
, location
.first_line
, "Identifier `%s' is implicitly declared outside of a module.\n", str
.c_str());
1744 } else if (flag_autowire
|| str
== "\\$global_clock") {
1745 AstNode
*auto_wire
= new AstNode(AST_AUTOWIRE
);
1746 auto_wire
->str
= str
;
1747 current_ast_mod
->children
.push_back(auto_wire
);
1748 current_scope
[str
] = auto_wire
;
1749 did_something
= true;
1751 log_file_error(filename
, location
.first_line
, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str
.c_str());
1754 if (id2ast
!= current_scope
[str
]) {
1755 id2ast
= current_scope
[str
];
1756 did_something
= true;
1760 // split memory access with bit select to individual statements
1761 if (type
== AST_IDENTIFIER
&& children
.size() == 2 && children
[0]->type
== AST_RANGE
&& children
[1]->type
== AST_RANGE
&& !in_lvalue
&& stage
== 2)
1763 if (id2ast
== NULL
|| id2ast
->type
!= AST_MEMORY
|| children
[0]->children
.size() != 1)
1764 log_file_error(filename
, location
.first_line
, "Invalid bit-select on memory access!\n");
1766 int mem_width
, mem_size
, addr_bits
;
1767 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
1769 int data_range_left
= id2ast
->children
[0]->range_left
;
1770 int data_range_right
= id2ast
->children
[0]->range_right
;
1772 if (id2ast
->children
[0]->range_swapped
)
1773 std::swap(data_range_left
, data_range_right
);
1775 std::stringstream sstr
;
1776 sstr
<< "$mem2bits$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
1777 std::string wire_id
= sstr
.str();
1779 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
1780 wire
->str
= wire_id
;
1782 wire
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
1783 current_ast_mod
->children
.push_back(wire
);
1784 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
1786 AstNode
*data
= clone();
1787 delete data
->children
[1];
1788 data
->children
.pop_back();
1790 AstNode
*assign
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), data
);
1791 assign
->children
[0]->str
= wire_id
;
1792 assign
->children
[0]->was_checked
= true;
1796 size_t assign_idx
= 0;
1797 while (assign_idx
< current_block
->children
.size() && current_block
->children
[assign_idx
] != current_block_child
)
1799 log_assert(assign_idx
< current_block
->children
.size());
1800 current_block
->children
.insert(current_block
->children
.begin()+assign_idx
, assign
);
1801 wire
->is_reg
= true;
1805 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
1806 proc
->children
[0]->children
.push_back(assign
);
1807 current_ast_mod
->children
.push_back(proc
);
1810 newNode
= new AstNode(AST_IDENTIFIER
, children
[1]->clone());
1811 newNode
->str
= wire_id
;
1812 newNode
->integer
= integer
; // save original number of dimensions for $size() etc.
1813 newNode
->id2ast
= wire
;
1817 if (type
== AST_WHILE
)
1818 log_file_error(filename
, location
.first_line
, "While loops are only allowed in constant functions!\n");
1820 if (type
== AST_REPEAT
)
1822 AstNode
*count
= children
[0];
1823 AstNode
*body
= children
[1];
1825 // eval count expression
1826 while (count
->simplify(true, false, false, stage
, 32, true, false)) { }
1828 if (count
->type
!= AST_CONSTANT
)
1829 log_file_error(filename
, location
.first_line
, "Repeat loops outside must have constant repeat counts!\n");
1831 // convert to a block with the body repeated n times
1834 for (int i
= 0; i
< count
->bitsAsConst().as_int(); i
++)
1835 children
.insert(children
.begin(), body
->clone());
1839 did_something
= true;
1842 // unroll for loops and generate-for blocks
1843 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && children
.size() != 0)
1845 AstNode
*init_ast
= children
[0];
1846 AstNode
*while_ast
= children
[1];
1847 AstNode
*next_ast
= children
[2];
1848 AstNode
*body_ast
= children
[3];
1850 while (body_ast
->type
== AST_GENBLOCK
&& body_ast
->str
.empty() &&
1851 body_ast
->children
.size() == 1 && body_ast
->children
.at(0)->type
== AST_GENBLOCK
)
1852 body_ast
= body_ast
->children
.at(0);
1854 const char* loop_type_str
= "procedural";
1855 const char* var_type_str
= "register";
1856 AstNodeType var_type
= AST_WIRE
;
1857 if (type
== AST_GENFOR
) {
1858 loop_type_str
= "generate";
1859 var_type_str
= "genvar";
1860 var_type
= AST_GENVAR
;
1863 if (init_ast
->type
!= AST_ASSIGN_EQ
)
1864 log_file_error(filename
, location
.first_line
, "Unsupported 1st expression of %s for-loop!\n", loop_type_str
);
1865 if (next_ast
->type
!= AST_ASSIGN_EQ
)
1866 log_file_error(filename
, location
.first_line
, "Unsupported 3rd expression of %s for-loop!\n", loop_type_str
);
1868 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= var_type
)
1869 log_file_error(filename
, location
.first_line
, "Left hand side of 1st expression of %s for-loop is not a %s!\n", loop_type_str
, var_type_str
);
1870 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= var_type
)
1871 log_file_error(filename
, location
.first_line
, "Left hand side of 3rd expression of %s for-loop is not a %s!\n", loop_type_str
, var_type_str
);
1873 if (init_ast
->children
[0]->id2ast
!= next_ast
->children
[0]->id2ast
)
1874 log_file_error(filename
, location
.first_line
, "Incompatible left-hand sides in 1st and 3rd expression of %s for-loop!\n", loop_type_str
);
1876 // eval 1st expression
1877 AstNode
*varbuf
= init_ast
->children
[1]->clone();
1879 int expr_width_hint
= -1;
1880 bool expr_sign_hint
= true;
1881 varbuf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1882 while (varbuf
->simplify(true, false, false, stage
, 32, true, false)) { }
1885 if (varbuf
->type
!= AST_CONSTANT
)
1886 log_file_error(filename
, location
.first_line
, "Right hand side of 1st expression of %s for-loop is not constant!\n", loop_type_str
);
1888 auto resolved
= current_scope
.at(init_ast
->children
[0]->str
);
1889 if (resolved
->range_valid
) {
1890 int const_size
= varbuf
->range_left
- varbuf
->range_right
;
1891 int resolved_size
= resolved
->range_left
- resolved
->range_right
;
1892 if (const_size
< resolved_size
) {
1893 for (int i
= const_size
; i
< resolved_size
; i
++)
1894 varbuf
->bits
.push_back(resolved
->is_signed
? varbuf
->bits
.back() : State::S0
);
1895 varbuf
->range_left
= resolved
->range_left
;
1896 varbuf
->range_right
= resolved
->range_right
;
1897 varbuf
->range_swapped
= resolved
->range_swapped
;
1898 varbuf
->range_valid
= resolved
->range_valid
;
1902 varbuf
= new AstNode(AST_LOCALPARAM
, varbuf
);
1903 varbuf
->str
= init_ast
->children
[0]->str
;
1905 AstNode
*backup_scope_varbuf
= current_scope
[varbuf
->str
];
1906 current_scope
[varbuf
->str
] = varbuf
;
1908 size_t current_block_idx
= 0;
1909 if (type
== AST_FOR
) {
1910 while (current_block_idx
< current_block
->children
.size() &&
1911 current_block
->children
[current_block_idx
] != current_block_child
)
1912 current_block_idx
++;
1917 // eval 2nd expression
1918 AstNode
*buf
= while_ast
->clone();
1920 int expr_width_hint
= -1;
1921 bool expr_sign_hint
= true;
1922 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1923 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, false)) { }
1926 if (buf
->type
!= AST_CONSTANT
)
1927 log_file_error(filename
, location
.first_line
, "2nd expression of %s for-loop is not constant!\n", loop_type_str
);
1929 if (buf
->integer
== 0) {
1936 int index
= varbuf
->children
[0]->integer
;
1937 log_assert(body_ast
->type
== AST_GENBLOCK
|| body_ast
->type
== AST_BLOCK
);
1938 log_assert(!body_ast
->str
.empty());
1939 buf
= body_ast
->clone();
1941 std::stringstream sstr
;
1942 sstr
<< buf
->str
<< "[" << index
<< "].";
1943 std::string prefix
= sstr
.str();
1945 // create a scoped localparam for the current value of the loop variable
1946 AstNode
*local_index
= varbuf
->clone();
1947 size_t pos
= local_index
->str
.rfind('.');
1948 if (pos
!= std::string::npos
) // remove outer prefix
1949 local_index
->str
= "\\" + local_index
->str
.substr(pos
+ 1);
1950 local_index
->str
= prefix_id(prefix
, local_index
->str
);
1951 current_scope
[local_index
->str
] = local_index
;
1952 current_ast_mod
->children
.push_back(local_index
);
1954 buf
->expand_genblock(prefix
);
1956 if (type
== AST_GENFOR
) {
1957 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1958 buf
->children
[i
]->simplify(const_fold
, false, false, stage
, -1, false, false);
1959 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1962 for (size_t i
= 0; i
< buf
->children
.size(); i
++)
1963 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
->children
[i
]);
1965 buf
->children
.clear();
1968 // eval 3rd expression
1969 buf
= next_ast
->children
[1]->clone();
1971 int expr_width_hint
= -1;
1972 bool expr_sign_hint
= true;
1973 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1974 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, true)) { }
1977 if (buf
->type
!= AST_CONSTANT
)
1978 log_file_error(filename
, location
.first_line
, "Right hand side of 3rd expression of %s for-loop is not constant (%s)!\n", loop_type_str
, type2str(buf
->type
).c_str());
1980 delete varbuf
->children
[0];
1981 varbuf
->children
[0] = buf
;
1984 if (type
== AST_FOR
) {
1985 AstNode
*buf
= next_ast
->clone();
1986 delete buf
->children
[1];
1987 buf
->children
[1] = varbuf
->children
[0]->clone();
1988 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
);
1991 current_scope
[varbuf
->str
] = backup_scope_varbuf
;
1994 did_something
= true;
1997 // check for local objects in unnamed block
1998 if (type
== AST_BLOCK
&& str
.empty())
2000 for (size_t i
= 0; i
< children
.size(); i
++)
2001 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
)
2003 log_assert(!VERILOG_FRONTEND::sv_mode
);
2004 log_file_error(children
[i
]->filename
, children
[i
]->location
.first_line
, "Local declaration in unnamed block is only supported in SystemVerilog mode!\n");
2008 // transform block with name
2009 if (type
== AST_BLOCK
&& !str
.empty())
2011 expand_genblock(str
+ ".");
2013 std::vector
<AstNode
*> new_children
;
2014 for (size_t i
= 0; i
< children
.size(); i
++)
2015 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
) {
2016 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
2017 current_ast_mod
->children
.push_back(children
[i
]);
2018 current_scope
[children
[i
]->str
] = children
[i
];
2020 new_children
.push_back(children
[i
]);
2022 children
.swap(new_children
);
2023 did_something
= true;
2027 // simplify unconditional generate block
2028 if (type
== AST_GENBLOCK
&& children
.size() != 0)
2031 expand_genblock(str
+ ".");
2034 for (size_t i
= 0; i
< children
.size(); i
++) {
2035 children
[i
]->simplify(const_fold
, false, false, stage
, -1, false, false);
2036 current_ast_mod
->children
.push_back(children
[i
]);
2040 did_something
= true;
2043 // simplify generate-if blocks
2044 if (type
== AST_GENIF
&& children
.size() != 0)
2046 AstNode
*buf
= children
[0]->clone();
2047 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2048 if (buf
->type
!= AST_CONSTANT
) {
2049 // for (auto f : log_files)
2050 // dumpAst(f, "verilog-ast> ");
2051 log_file_error(filename
, location
.first_line
, "Condition for generate if is not constant!\n");
2053 if (buf
->asBool() != 0) {
2055 buf
= children
[1]->clone();
2058 buf
= children
.size() > 2 ? children
[2]->clone() : NULL
;
2063 if (buf
->type
!= AST_GENBLOCK
)
2064 buf
= new AstNode(AST_GENBLOCK
, buf
);
2066 if (!buf
->str
.empty()) {
2067 buf
->expand_genblock(buf
->str
+ ".");
2070 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
2071 buf
->children
[i
]->simplify(const_fold
, false, false, stage
, -1, false, false);
2072 current_ast_mod
->children
.push_back(buf
->children
[i
]);
2075 buf
->children
.clear();
2080 did_something
= true;
2083 // simplify generate-case blocks
2084 if (type
== AST_GENCASE
&& children
.size() != 0)
2086 AstNode
*buf
= children
[0]->clone();
2087 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2088 if (buf
->type
!= AST_CONSTANT
) {
2089 // for (auto f : log_files)
2090 // dumpAst(f, "verilog-ast> ");
2091 log_file_error(filename
, location
.first_line
, "Condition for generate case is not constant!\n");
2094 bool ref_signed
= buf
->is_signed
;
2095 RTLIL::Const ref_value
= buf
->bitsAsConst();
2098 AstNode
*selected_case
= NULL
;
2099 for (size_t i
= 1; i
< children
.size(); i
++)
2101 log_assert(children
.at(i
)->type
== AST_COND
|| children
.at(i
)->type
== AST_CONDX
|| children
.at(i
)->type
== AST_CONDZ
);
2103 AstNode
*this_genblock
= NULL
;
2104 for (auto child
: children
.at(i
)->children
) {
2105 log_assert(this_genblock
== NULL
);
2106 if (child
->type
== AST_GENBLOCK
)
2107 this_genblock
= child
;
2110 for (auto child
: children
.at(i
)->children
)
2112 if (child
->type
== AST_DEFAULT
) {
2113 if (selected_case
== NULL
)
2114 selected_case
= this_genblock
;
2117 if (child
->type
== AST_GENBLOCK
)
2120 buf
= child
->clone();
2121 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, true)) { }
2122 if (buf
->type
!= AST_CONSTANT
) {
2123 // for (auto f : log_files)
2124 // dumpAst(f, "verilog-ast> ");
2125 log_file_error(filename
, location
.first_line
, "Expression in generate case is not constant!\n");
2128 bool is_selected
= RTLIL::const_eq(ref_value
, buf
->bitsAsConst(), ref_signed
&& buf
->is_signed
, ref_signed
&& buf
->is_signed
, 1).as_bool();
2132 selected_case
= this_genblock
;
2133 i
= children
.size();
2139 if (selected_case
!= NULL
)
2141 log_assert(selected_case
->type
== AST_GENBLOCK
);
2142 buf
= selected_case
->clone();
2144 if (!buf
->str
.empty()) {
2145 buf
->expand_genblock(buf
->str
+ ".");
2148 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
2149 buf
->children
[i
]->simplify(const_fold
, false, false, stage
, -1, false, false);
2150 current_ast_mod
->children
.push_back(buf
->children
[i
]);
2153 buf
->children
.clear();
2158 did_something
= true;
2161 // unroll cell arrays
2162 if (type
== AST_CELLARRAY
)
2164 if (!children
.at(0)->range_valid
)
2165 log_file_error(filename
, location
.first_line
, "Non-constant array range on cell array.\n");
2167 newNode
= new AstNode(AST_GENBLOCK
);
2168 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;
2170 for (int i
= 0; i
< num
; i
++) {
2171 int idx
= children
.at(0)->range_left
> children
.at(0)->range_right
? children
.at(0)->range_right
+ i
: children
.at(0)->range_right
- i
;
2172 AstNode
*new_cell
= children
.at(1)->clone();
2173 newNode
->children
.push_back(new_cell
);
2174 new_cell
->str
+= stringf("[%d]", idx
);
2175 if (new_cell
->type
== AST_PRIMITIVE
) {
2176 log_file_error(filename
, location
.first_line
, "Cell arrays of primitives are currently not supported.\n");
2178 log_assert(new_cell
->children
.at(0)->type
== AST_CELLTYPE
);
2179 new_cell
->children
.at(0)->str
= stringf("$array:%d:%d:%s", i
, num
, new_cell
->children
.at(0)->str
.c_str());
2186 // replace primitives with assignments
2187 if (type
== AST_PRIMITIVE
)
2189 if (children
.size() < 2)
2190 log_file_error(filename
, location
.first_line
, "Insufficient number of arguments for primitive `%s'!\n", str
.c_str());
2192 std::vector
<AstNode
*> children_list
;
2193 for (auto child
: children
) {
2194 log_assert(child
->type
== AST_ARGUMENT
);
2195 log_assert(child
->children
.size() == 1);
2196 children_list
.push_back(child
->children
[0]);
2197 child
->children
.clear();
2202 if (str
== "bufif0" || str
== "bufif1" || str
== "notif0" || str
== "notif1")
2204 if (children_list
.size() != 3)
2205 log_file_error(filename
, location
.first_line
, "Invalid number of arguments for primitive `%s'!\n", str
.c_str());
2207 std::vector
<RTLIL::State
> z_const(1, RTLIL::State::Sz
);
2209 AstNode
*mux_input
= children_list
.at(1);
2210 if (str
== "notif0" || str
== "notif1") {
2211 mux_input
= new AstNode(AST_BIT_NOT
, mux_input
);
2213 AstNode
*node
= new AstNode(AST_TERNARY
, children_list
.at(2));
2214 if (str
== "bufif0") {
2215 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
2216 node
->children
.push_back(mux_input
);
2218 node
->children
.push_back(mux_input
);
2219 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
2224 children
.push_back(children_list
.at(0));
2225 children
.back()->was_checked
= true;
2226 children
.push_back(node
);
2227 did_something
= true;
2229 else if (str
== "buf" || str
== "not")
2231 AstNode
*input
= children_list
.back();
2233 input
= new AstNode(AST_BIT_NOT
, input
);
2235 newNode
= new AstNode(AST_GENBLOCK
);
2236 for (auto it
= children_list
.begin(); it
!= std::prev(children_list
.end()); it
++) {
2237 newNode
->children
.push_back(new AstNode(AST_ASSIGN
, *it
, input
->clone()));
2238 newNode
->children
.back()->was_checked
= true;
2242 did_something
= true;
2246 AstNodeType op_type
= AST_NONE
;
2247 bool invert_results
= false;
2250 op_type
= AST_BIT_AND
;
2252 op_type
= AST_BIT_AND
, invert_results
= true;
2254 op_type
= AST_BIT_OR
;
2256 op_type
= AST_BIT_OR
, invert_results
= true;
2258 op_type
= AST_BIT_XOR
;
2260 op_type
= AST_BIT_XOR
, invert_results
= true;
2261 log_assert(op_type
!= AST_NONE
);
2263 AstNode
*node
= children_list
[1];
2264 if (op_type
!= AST_POS
)
2265 for (size_t i
= 2; i
< children_list
.size(); i
++) {
2266 node
= new AstNode(op_type
, node
, children_list
[i
]);
2267 node
->location
= location
;
2270 node
= new AstNode(AST_BIT_NOT
, node
);
2274 children
.push_back(children_list
[0]);
2275 children
.back()->was_checked
= true;
2276 children
.push_back(node
);
2277 did_something
= true;
2281 // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
2282 // either a big case block that selects the correct single-bit assignment, or mask and
2283 // shift operations.
2284 if (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
)
2286 if (children
[0]->type
!= AST_IDENTIFIER
|| children
[0]->children
.size() == 0)
2287 goto skip_dynamic_range_lvalue_expansion
;
2288 if (children
[0]->children
[0]->range_valid
|| did_something
)
2289 goto skip_dynamic_range_lvalue_expansion
;
2290 if (children
[0]->id2ast
== NULL
|| children
[0]->id2ast
->type
!= AST_WIRE
)
2291 goto skip_dynamic_range_lvalue_expansion
;
2292 if (!children
[0]->id2ast
->range_valid
)
2293 goto skip_dynamic_range_lvalue_expansion
;
2295 int source_width
= children
[0]->id2ast
->range_left
- children
[0]->id2ast
->range_right
+ 1;
2296 int result_width
= 1;
2298 AstNode
*shift_expr
= NULL
;
2299 AstNode
*range
= children
[0]->children
[0];
2301 if (range
->children
.size() == 1) {
2302 shift_expr
= range
->children
[0]->clone();
2304 shift_expr
= range
->children
[1]->clone();
2305 AstNode
*left_at_zero_ast
= range
->children
[0]->clone();
2306 AstNode
*right_at_zero_ast
= range
->children
[1]->clone();
2307 while (left_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
2308 while (right_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
2309 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
2310 log_file_error(filename
, location
.first_line
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
2311 result_width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
2312 delete left_at_zero_ast
;
2313 delete right_at_zero_ast
;
2316 bool use_case_method
= false;
2318 if (children
[0]->id2ast
->attributes
.count(ID::nowrshmsk
)) {
2319 AstNode
*node
= children
[0]->id2ast
->attributes
.at(ID::nowrshmsk
);
2320 while (node
->simplify(true, false, false, stage
, -1, false, false)) { }
2321 if (node
->type
!= AST_CONSTANT
)
2322 log_file_error(filename
, location
.first_line
, "Non-constant value for `nowrshmsk' attribute on `%s'!\n", children
[0]->id2ast
->str
.c_str());
2323 if (node
->asAttrConst().as_bool())
2324 use_case_method
= true;
2327 if (!use_case_method
&& current_always
->detect_latch(children
[0]->str
))
2328 use_case_method
= true;
2330 if (use_case_method
)
2334 did_something
= true;
2335 newNode
= new AstNode(AST_CASE
, shift_expr
);
2336 for (int i
= 0; i
< source_width
; i
++) {
2337 int start_bit
= children
[0]->id2ast
->range_right
+ i
;
2338 int end_bit
= std::min(start_bit
+result_width
,source_width
) - 1;
2339 AstNode
*cond
= new AstNode(AST_COND
, mkconst_int(start_bit
, true));
2340 AstNode
*lvalue
= children
[0]->clone();
2341 lvalue
->delete_children();
2342 lvalue
->children
.push_back(new AstNode(AST_RANGE
,
2343 mkconst_int(end_bit
, true), mkconst_int(start_bit
, true)));
2344 cond
->children
.push_back(new AstNode(AST_BLOCK
, new AstNode(type
, lvalue
, children
[1]->clone())));
2345 newNode
->children
.push_back(cond
);
2350 // mask and shift operations, disabled for now
2352 AstNode
*wire_mask
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(source_width
-1, true), mkconst_int(0, true)));
2353 wire_mask
->str
= stringf("$bitselwrite$mask$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
2354 wire_mask
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
2355 wire_mask
->is_logic
= true;
2356 while (wire_mask
->simplify(true, false, false, 1, -1, false, false)) { }
2357 current_ast_mod
->children
.push_back(wire_mask
);
2359 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(source_width
-1, true), mkconst_int(0, true)));
2360 wire_data
->str
= stringf("$bitselwrite$data$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
2361 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
2362 wire_data
->is_logic
= true;
2363 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
2364 current_ast_mod
->children
.push_back(wire_data
);
2366 did_something
= true;
2367 newNode
= new AstNode(AST_BLOCK
);
2369 AstNode
*lvalue
= children
[0]->clone();
2370 lvalue
->delete_children();
2372 AstNode
*ref_mask
= new AstNode(AST_IDENTIFIER
);
2373 ref_mask
->str
= wire_mask
->str
;
2374 ref_mask
->id2ast
= wire_mask
;
2375 ref_mask
->was_checked
= true;
2377 AstNode
*ref_data
= new AstNode(AST_IDENTIFIER
);
2378 ref_data
->str
= wire_data
->str
;
2379 ref_data
->id2ast
= wire_data
;
2380 ref_data
->was_checked
= true;
2382 AstNode
*old_data
= lvalue
->clone();
2383 if (type
== AST_ASSIGN_LE
)
2384 old_data
->lookahead
= true;
2386 AstNode
*shamt
= shift_expr
;
2388 int shamt_width_hint
= 0;
2389 bool shamt_sign_hint
= true;
2390 shamt
->detectSignWidth(shamt_width_hint
, shamt_sign_hint
);
2392 int start_bit
= children
[0]->id2ast
->range_right
;
2393 bool use_shift
= shamt_sign_hint
;
2395 if (start_bit
!= 0) {
2396 shamt
= new AstNode(AST_SUB
, shamt
, mkconst_int(start_bit
, true));
2402 t
= mkconst_bits(std::vector
<RTLIL::State
>(result_width
, State::S1
), false);
2404 t
= new AstNode(AST_SHIFT
, t
, new AstNode(AST_NEG
, shamt
->clone()));
2406 t
= new AstNode(AST_SHIFT_LEFT
, t
, shamt
->clone());
2407 t
= new AstNode(AST_ASSIGN_EQ
, ref_mask
->clone(), t
);
2408 newNode
->children
.push_back(t
);
2410 t
= new AstNode(AST_BIT_AND
, mkconst_bits(std::vector
<RTLIL::State
>(result_width
, State::S1
), false), children
[1]->clone());
2412 t
= new AstNode(AST_SHIFT
, t
, new AstNode(AST_NEG
, shamt
));
2414 t
= new AstNode(AST_SHIFT_LEFT
, t
, shamt
);
2415 t
= new AstNode(AST_ASSIGN_EQ
, ref_data
->clone(), t
);
2416 newNode
->children
.push_back(t
);
2418 t
= new AstNode(AST_BIT_AND
, old_data
, new AstNode(AST_BIT_NOT
, ref_mask
));
2419 t
= new AstNode(AST_BIT_OR
, t
, ref_data
);
2420 t
= new AstNode(type
, lvalue
, t
);
2421 newNode
->children
.push_back(t
);
2426 skip_dynamic_range_lvalue_expansion
:;
2428 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && current_block
!= NULL
)
2430 std::stringstream sstr
;
2431 sstr
<< "$formal$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
2432 std::string id_check
= sstr
.str() + "_CHECK", id_en
= sstr
.str() + "_EN";
2434 AstNode
*wire_check
= new AstNode(AST_WIRE
);
2435 wire_check
->str
= id_check
;
2436 wire_check
->was_checked
= true;
2437 current_ast_mod
->children
.push_back(wire_check
);
2438 current_scope
[wire_check
->str
] = wire_check
;
2439 while (wire_check
->simplify(true, false, false, 1, -1, false, false)) { }
2441 AstNode
*wire_en
= new AstNode(AST_WIRE
);
2442 wire_en
->str
= id_en
;
2443 wire_en
->was_checked
= true;
2444 current_ast_mod
->children
.push_back(wire_en
);
2445 if (current_always_clocked
) {
2446 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)))));
2447 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->str
= id_en
;
2448 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->was_checked
= true;
2450 current_scope
[wire_en
->str
] = wire_en
;
2451 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
2453 AstNode
*check_defval
;
2454 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
2455 check_defval
= new AstNode(AST_REDUCE_BOOL
, children
[0]->clone());
2457 std::vector
<RTLIL::State
> x_bit
;
2458 x_bit
.push_back(RTLIL::State::Sx
);
2459 check_defval
= mkconst_bits(x_bit
, false);
2462 AstNode
*assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), check_defval
);
2463 assign_check
->children
[0]->str
= id_check
;
2464 assign_check
->children
[0]->was_checked
= true;
2466 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, 1));
2467 assign_en
->children
[0]->str
= id_en
;
2468 assign_en
->children
[0]->was_checked
= true;
2470 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
2471 default_signals
->children
.push_back(assign_check
);
2472 default_signals
->children
.push_back(assign_en
);
2473 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
2475 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
2476 assign_check
= nullptr;
2478 assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_REDUCE_BOOL
, children
[0]->clone()));
2479 assign_check
->children
[0]->str
= id_check
;
2480 assign_check
->children
[0]->was_checked
= true;
2483 if (current_always
== nullptr || current_always
->type
!= AST_INITIAL
) {
2484 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(1, false, 1));
2486 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_FCALL
));
2487 assign_en
->children
[1]->str
= "\\$initstate";
2489 assign_en
->children
[0]->str
= id_en
;
2490 assign_en
->children
[0]->was_checked
= true;
2492 newNode
= new AstNode(AST_BLOCK
);
2493 if (assign_check
!= nullptr)
2494 newNode
->children
.push_back(assign_check
);
2495 newNode
->children
.push_back(assign_en
);
2497 AstNode
*assertnode
= new AstNode(type
);
2498 assertnode
->location
= location
;
2499 assertnode
->str
= str
;
2500 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
2501 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
2502 assertnode
->children
[0]->str
= id_check
;
2503 assertnode
->children
[1]->str
= id_en
;
2504 assertnode
->attributes
.swap(attributes
);
2505 current_ast_mod
->children
.push_back(assertnode
);
2510 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && children
.size() == 1)
2512 children
.push_back(mkconst_int(1, false, 1));
2513 did_something
= true;
2516 // found right-hand side identifier for memory -> replace with memory read port
2517 if (stage
> 1 && type
== AST_IDENTIFIER
&& id2ast
!= NULL
&& id2ast
->type
== AST_MEMORY
&& !in_lvalue
&&
2518 children
.size() == 1 && children
[0]->type
== AST_RANGE
&& children
[0]->children
.size() == 1) {
2519 newNode
= new AstNode(AST_MEMRD
, children
[0]->children
[0]->clone());
2521 newNode
->id2ast
= id2ast
;
2525 // assignment with nontrivial member in left-hand concat expression -> split assignment
2526 if ((type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_CONCAT
&& width_hint
> 0)
2528 bool found_nontrivial_member
= false;
2530 for (auto child
: children
[0]->children
) {
2531 if (child
->type
== AST_IDENTIFIER
&& child
->id2ast
!= NULL
&& child
->id2ast
->type
== AST_MEMORY
)
2532 found_nontrivial_member
= true;
2535 if (found_nontrivial_member
)
2537 newNode
= new AstNode(AST_BLOCK
);
2539 AstNode
*wire_tmp
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
2540 wire_tmp
->str
= stringf("$splitcmplxassign$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
2541 current_ast_mod
->children
.push_back(wire_tmp
);
2542 current_scope
[wire_tmp
->str
] = wire_tmp
;
2543 wire_tmp
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
2544 while (wire_tmp
->simplify(true, false, false, 1, -1, false, false)) { }
2545 wire_tmp
->is_logic
= true;
2547 AstNode
*wire_tmp_id
= new AstNode(AST_IDENTIFIER
);
2548 wire_tmp_id
->str
= wire_tmp
->str
;
2550 newNode
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, wire_tmp_id
, children
[1]->clone()));
2551 newNode
->children
.back()->was_checked
= true;
2554 for (auto child
: children
[0]->children
)
2556 int child_width_hint
= -1;
2557 bool child_sign_hint
= true;
2558 child
->detectSignWidth(child_width_hint
, child_sign_hint
);
2560 AstNode
*rhs
= wire_tmp_id
->clone();
2561 rhs
->children
.push_back(new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+child_width_hint
-1, true), AstNode::mkconst_int(cursor
, true)));
2562 newNode
->children
.push_back(new AstNode(type
, child
->clone(), rhs
));
2564 cursor
+= child_width_hint
;
2571 // assignment with memory in left-hand side expression -> replace with memory write port
2572 if (stage
> 1 && (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_IDENTIFIER
&&
2573 children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
&& children
[0]->id2ast
->children
.size() >= 2 &&
2574 children
[0]->id2ast
->children
[0]->range_valid
&& children
[0]->id2ast
->children
[1]->range_valid
&&
2575 (children
[0]->children
.size() == 1 || children
[0]->children
.size() == 2) && children
[0]->children
[0]->type
== AST_RANGE
)
2577 std::stringstream sstr
;
2578 sstr
<< "$memwr$" << children
[0]->str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
2579 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA", id_en
= sstr
.str() + "_EN";
2581 int mem_width
, mem_size
, addr_bits
;
2582 bool mem_signed
= children
[0]->id2ast
->is_signed
;
2583 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
2585 newNode
= new AstNode(AST_BLOCK
);
2586 AstNode
*defNode
= new AstNode(AST_BLOCK
);
2588 int data_range_left
= children
[0]->id2ast
->children
[0]->range_left
;
2589 int data_range_right
= children
[0]->id2ast
->children
[0]->range_right
;
2590 int mem_data_range_offset
= std::min(data_range_left
, data_range_right
);
2592 int addr_width_hint
= -1;
2593 bool addr_sign_hint
= true;
2594 children
[0]->children
[0]->children
[0]->detectSignWidthWorker(addr_width_hint
, addr_sign_hint
);
2595 addr_bits
= std::max(addr_bits
, addr_width_hint
);
2597 std::vector
<RTLIL::State
> x_bits_addr
, x_bits_data
, set_bits_en
;
2598 for (int i
= 0; i
< addr_bits
; i
++)
2599 x_bits_addr
.push_back(RTLIL::State::Sx
);
2600 for (int i
= 0; i
< mem_width
; i
++)
2601 x_bits_data
.push_back(RTLIL::State::Sx
);
2602 for (int i
= 0; i
< mem_width
; i
++)
2603 set_bits_en
.push_back(RTLIL::State::S1
);
2605 AstNode
*node_addr
= nullptr;
2606 if (children
[0]->children
[0]->children
[0]->isConst()) {
2607 node_addr
= children
[0]->children
[0]->children
[0]->clone();
2609 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
2610 wire_addr
->str
= id_addr
;
2611 wire_addr
->was_checked
= true;
2612 current_ast_mod
->children
.push_back(wire_addr
);
2613 current_scope
[wire_addr
->str
] = wire_addr
;
2614 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
2616 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_addr
, false));
2617 assign_addr
->children
[0]->str
= id_addr
;
2618 assign_addr
->children
[0]->was_checked
= true;
2619 defNode
->children
.push_back(assign_addr
);
2621 assign_addr
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
2622 assign_addr
->children
[0]->str
= id_addr
;
2623 assign_addr
->children
[0]->was_checked
= true;
2624 newNode
->children
.push_back(assign_addr
);
2626 node_addr
= new AstNode(AST_IDENTIFIER
);
2627 node_addr
->str
= id_addr
;
2630 AstNode
*node_data
= nullptr;
2631 if (children
[0]->children
.size() == 1 && children
[1]->isConst()) {
2632 node_data
= children
[1]->clone();
2634 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
2635 wire_data
->str
= id_data
;
2636 wire_data
->was_checked
= true;
2637 wire_data
->is_signed
= mem_signed
;
2638 current_ast_mod
->children
.push_back(wire_data
);
2639 current_scope
[wire_data
->str
] = wire_data
;
2640 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
2642 AstNode
*assign_data
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_data
, false));
2643 assign_data
->children
[0]->str
= id_data
;
2644 assign_data
->children
[0]->was_checked
= true;
2645 defNode
->children
.push_back(assign_data
);
2647 node_data
= new AstNode(AST_IDENTIFIER
);
2648 node_data
->str
= id_data
;
2651 AstNode
*wire_en
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
2652 wire_en
->str
= id_en
;
2653 wire_en
->was_checked
= true;
2654 current_ast_mod
->children
.push_back(wire_en
);
2655 current_scope
[wire_en
->str
] = wire_en
;
2656 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
2658 AstNode
*assign_en_first
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, mem_width
));
2659 assign_en_first
->children
[0]->str
= id_en
;
2660 assign_en_first
->children
[0]->was_checked
= true;
2661 defNode
->children
.push_back(assign_en_first
);
2663 AstNode
*node_en
= new AstNode(AST_IDENTIFIER
);
2664 node_en
->str
= id_en
;
2666 if (!defNode
->children
.empty())
2667 current_top_block
->children
.insert(current_top_block
->children
.begin(), defNode
);
2671 AstNode
*assign_data
= nullptr;
2672 AstNode
*assign_en
= nullptr;
2673 if (children
[0]->children
.size() == 2)
2675 if (children
[0]->children
[1]->range_valid
)
2677 int offset
= children
[0]->children
[1]->range_right
;
2678 int width
= children
[0]->children
[1]->range_left
- offset
+ 1;
2679 offset
-= mem_data_range_offset
;
2681 std::vector
<RTLIL::State
> padding_x(offset
, RTLIL::State::Sx
);
2683 assign_data
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
),
2684 new AstNode(AST_CONCAT
, mkconst_bits(padding_x
, false), children
[1]->clone()));
2685 assign_data
->children
[0]->str
= id_data
;
2686 assign_data
->children
[0]->was_checked
= true;
2688 for (int i
= 0; i
< mem_width
; i
++)
2689 set_bits_en
[i
] = offset
<= i
&& i
< offset
+width
? RTLIL::State::S1
: RTLIL::State::S0
;
2690 assign_en
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
2691 assign_en
->children
[0]->str
= id_en
;
2692 assign_en
->children
[0]->was_checked
= true;
2696 AstNode
*the_range
= children
[0]->children
[1];
2697 AstNode
*left_at_zero_ast
= the_range
->children
[0]->clone();
2698 AstNode
*right_at_zero_ast
= the_range
->children
.size() >= 2 ? the_range
->children
[1]->clone() : left_at_zero_ast
->clone();
2699 AstNode
*offset_ast
= right_at_zero_ast
->clone();
2701 if (mem_data_range_offset
)
2702 offset_ast
= new AstNode(AST_SUB
, offset_ast
, mkconst_int(mem_data_range_offset
, true));
2704 while (left_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
2705 while (right_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
2706 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
2707 log_file_error(filename
, location
.first_line
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
2708 int width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
2710 assign_data
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
),
2711 new AstNode(AST_SHIFT_LEFT
, children
[1]->clone(), offset_ast
->clone()));
2712 assign_data
->children
[0]->str
= id_data
;
2713 assign_data
->children
[0]->was_checked
= true;
2715 for (int i
= 0; i
< mem_width
; i
++)
2716 set_bits_en
[i
] = i
< width
? RTLIL::State::S1
: RTLIL::State::S0
;
2717 assign_en
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
),
2718 new AstNode(AST_SHIFT_LEFT
, mkconst_bits(set_bits_en
, false), offset_ast
->clone()));
2719 assign_en
->children
[0]->str
= id_en
;
2720 assign_en
->children
[0]->was_checked
= true;
2722 delete left_at_zero_ast
;
2723 delete right_at_zero_ast
;
2729 if (!(children
[0]->children
.size() == 1 && children
[1]->isConst())) {
2730 assign_data
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), children
[1]->clone());
2731 assign_data
->children
[0]->str
= id_data
;
2732 assign_data
->children
[0]->was_checked
= true;
2735 assign_en
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
2736 assign_en
->children
[0]->str
= id_en
;
2737 assign_en
->children
[0]->was_checked
= true;
2740 newNode
->children
.push_back(assign_data
);
2742 newNode
->children
.push_back(assign_en
);
2745 if (current_always
->type
== AST_INITIAL
)
2746 wrnode
= new AstNode(AST_MEMINIT
, node_addr
, node_data
, node_en
, mkconst_int(1, false));
2748 wrnode
= new AstNode(AST_MEMWR
, node_addr
, node_data
, node_en
);
2749 wrnode
->str
= children
[0]->str
;
2750 wrnode
->id2ast
= children
[0]->id2ast
;
2751 wrnode
->location
= location
;
2752 if (wrnode
->type
== AST_MEMWR
) {
2753 int portid
= current_memwr_count
[wrnode
->str
]++;
2754 wrnode
->children
.push_back(mkconst_int(portid
, false));
2755 std::vector
<RTLIL::State
> priority_mask
;
2756 for (int i
= 0; i
< portid
; i
++) {
2757 bool has_prio
= current_memwr_visible
[wrnode
->str
].count(i
);
2758 priority_mask
.push_back(State(has_prio
));
2760 wrnode
->children
.push_back(mkconst_bits(priority_mask
, false));
2761 current_memwr_visible
[wrnode
->str
].insert(portid
);
2762 current_always
->children
.push_back(wrnode
);
2764 current_ast_mod
->children
.push_back(wrnode
);
2767 if (newNode
->children
.empty()) {
2769 newNode
= new AstNode();
2774 // replace function and task calls with the code from the function or task
2775 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && !str
.empty())
2777 if (type
== AST_FCALL
)
2779 if (str
== "\\$initstate")
2781 int myidx
= autoidx
++;
2783 AstNode
*wire
= new AstNode(AST_WIRE
);
2784 wire
->str
= stringf("$initstate$%d_wire", myidx
);
2785 current_ast_mod
->children
.push_back(wire
);
2786 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2788 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
), new AstNode(AST_ARGUMENT
, new AstNode(AST_IDENTIFIER
)));
2789 cell
->str
= stringf("$initstate$%d", myidx
);
2790 cell
->children
[0]->str
= "$initstate";
2791 cell
->children
[1]->str
= "\\Y";
2792 cell
->children
[1]->children
[0]->str
= wire
->str
;
2793 cell
->children
[1]->children
[0]->id2ast
= wire
;
2794 current_ast_mod
->children
.push_back(cell
);
2795 while (cell
->simplify(true, false, false, 1, -1, false, false)) { }
2797 newNode
= new AstNode(AST_IDENTIFIER
);
2798 newNode
->str
= wire
->str
;
2799 newNode
->id2ast
= wire
;
2803 if (str
== "\\$past")
2806 goto replace_fcall_later
;
2810 if (GetSize(children
) != 1 && GetSize(children
) != 2)
2811 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1 or 2.\n",
2812 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2814 if (!current_always_clocked
)
2815 log_file_error(filename
, location
.first_line
, "System function %s is only allowed in clocked blocks.\n",
2816 RTLIL::unescape_id(str
).c_str());
2818 if (GetSize(children
) == 2)
2820 AstNode
*buf
= children
[1]->clone();
2821 while (buf
->simplify(true, false, false, stage
, -1, false, false)) { }
2822 if (buf
->type
!= AST_CONSTANT
)
2823 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
2825 num_steps
= buf
->asInt(true);
2829 AstNode
*block
= nullptr;
2831 for (auto child
: current_always
->children
)
2832 if (child
->type
== AST_BLOCK
)
2835 log_assert(block
!= nullptr);
2837 if (num_steps
== 0) {
2838 newNode
= children
[0]->clone();
2842 int myidx
= autoidx
++;
2843 AstNode
*outreg
= nullptr;
2845 for (int i
= 0; i
< num_steps
; i
++)
2847 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
2848 mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
2850 reg
->str
= stringf("$past$%s:%d$%d$%d", filename
.c_str(), location
.first_line
, myidx
, i
);
2853 current_ast_mod
->children
.push_back(reg
);
2855 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
2857 AstNode
*regid
= new AstNode(AST_IDENTIFIER
);
2858 regid
->str
= reg
->str
;
2859 regid
->id2ast
= reg
;
2860 regid
->was_checked
= true;
2862 AstNode
*rhs
= nullptr;
2864 if (outreg
== nullptr) {
2865 rhs
= children
.at(0)->clone();
2867 rhs
= new AstNode(AST_IDENTIFIER
);
2868 rhs
->str
= outreg
->str
;
2869 rhs
->id2ast
= outreg
;
2872 block
->children
.push_back(new AstNode(AST_ASSIGN_LE
, regid
, rhs
));
2876 newNode
= new AstNode(AST_IDENTIFIER
);
2877 newNode
->str
= outreg
->str
;
2878 newNode
->id2ast
= outreg
;
2882 if (str
== "\\$stable" || str
== "\\$rose" || str
== "\\$fell" || str
== "\\$changed")
2884 if (GetSize(children
) != 1)
2885 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2886 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2888 if (!current_always_clocked
)
2889 log_file_error(filename
, location
.first_line
, "System function %s is only allowed in clocked blocks.\n",
2890 RTLIL::unescape_id(str
).c_str());
2892 AstNode
*present
= children
.at(0)->clone();
2893 AstNode
*past
= clone();
2894 past
->str
= "\\$past";
2896 if (str
== "\\$stable")
2897 newNode
= new AstNode(AST_EQ
, past
, present
);
2899 else if (str
== "\\$changed")
2900 newNode
= new AstNode(AST_NE
, past
, present
);
2902 else if (str
== "\\$rose")
2903 newNode
= new AstNode(AST_LOGIC_AND
,
2904 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false))),
2905 new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false)));
2907 else if (str
== "\\$fell")
2908 newNode
= new AstNode(AST_LOGIC_AND
,
2909 new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false)),
2910 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false))));
2918 // $anyconst and $anyseq are mapped in AstNode::genRTLIL()
2919 if (str
== "\\$anyconst" || str
== "\\$anyseq" || str
== "\\$allconst" || str
== "\\$allseq") {
2920 recursion_counter
--;
2924 if (str
== "\\$clog2")
2926 if (children
.size() != 1)
2927 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2928 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2930 AstNode
*buf
= children
[0]->clone();
2931 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2932 if (buf
->type
!= AST_CONSTANT
)
2933 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
2935 RTLIL::Const arg_value
= buf
->bitsAsConst();
2936 if (arg_value
.as_bool())
2937 arg_value
= const_sub(arg_value
, 1, false, false, GetSize(arg_value
));
2940 uint32_t result
= 0;
2941 for (size_t i
= 0; i
< arg_value
.bits
.size(); i
++)
2942 if (arg_value
.bits
.at(i
) == RTLIL::State::S1
)
2945 newNode
= mkconst_int(result
, true);
2949 if (str
== "\\$size" || str
== "\\$bits" || str
== "\\$high" || str
== "\\$low" || str
== "\\$left" || str
== "\\$right")
2952 if (str
== "\\$bits") {
2953 if (children
.size() != 1)
2954 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2955 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2957 if (children
.size() != 1 && children
.size() != 2)
2958 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1 or 2.\n",
2959 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2960 if (children
.size() == 2) {
2961 AstNode
*buf
= children
[1]->clone();
2962 // Evaluate constant expression
2963 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2964 dim
= buf
->asInt(false);
2968 AstNode
*buf
= children
[0]->clone();
2970 int result
, high
= 0, low
= 0, left
= 0, right
= 0, width
= 1; // defaults for a simple wire
2971 AstNode
*id_ast
= NULL
;
2974 //while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2975 buf
->detectSignWidth(width_hint
, sign_hint
);
2977 if (buf
->type
== AST_IDENTIFIER
) {
2978 id_ast
= buf
->id2ast
;
2979 if (id_ast
== NULL
&& current_scope
.count(buf
->str
))
2980 id_ast
= current_scope
.at(buf
->str
);
2982 log_file_error(filename
, location
.first_line
, "Failed to resolve identifier %s for width detection!\n", buf
->str
.c_str());
2983 // a slice of our identifier means we advance to the next dimension, e.g. $size(a[3])
2984 if (buf
->children
.size() > 0) {
2985 // something is hanging below this identifier
2986 if (buf
->children
[0]->type
== AST_RANGE
&& buf
->integer
== 0)
2987 // if integer == 0, this node was originally created as AST_RANGE so it's dimension is 1
2989 // more than one range, e.g. $size(a[3][2])
2990 else // created an AST_MULTIRANGE, converted to AST_RANGE, but original dimension saved in 'integer' field
2991 dim
+= buf
->integer
; // increment by multirange size
2994 // wire x; ==> AST_WIRE, no AST_RANGE children
2995 // wire [1:0]x; ==> AST_WIRE, AST_RANGE children
2996 // wire [1:0]x[1:0]; ==> AST_MEMORY, two AST_RANGE children (1st for packed, 2nd for unpacked)
2997 // wire [1:0]x[1:0][1:0]; ==> AST_MEMORY, one AST_RANGE child (0) for packed, then AST_MULTIRANGE child (1) for unpacked
2998 // (updated: actually by the time we are here, AST_MULTIRANGE is converted into one big AST_RANGE)
2999 // case 0 handled by default
3000 if ((id_ast
->type
== AST_WIRE
|| id_ast
->type
== AST_MEMORY
) && id_ast
->children
.size() > 0) {
3001 // handle packed array left/right for case 1, and cases 2/3 when requesting the last dimension (packed side)
3002 AstNode
*wire_range
= id_ast
->children
[0];
3003 left
= wire_range
->children
[0]->integer
;
3004 right
= wire_range
->children
[1]->integer
;
3005 high
= max(left
, right
);
3006 low
= min(left
, right
);
3008 if (id_ast
->type
== AST_MEMORY
) {
3009 // We got here only if the argument is a memory
3010 // Otherwise $size() and $bits() return the expression width
3011 AstNode
*mem_range
= id_ast
->children
[1];
3012 if (str
== "\\$bits") {
3013 if (mem_range
->type
== AST_RANGE
) {
3014 if (!mem_range
->range_valid
)
3015 log_file_error(filename
, location
.first_line
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
3016 mem_depth
= mem_range
->range_left
- mem_range
->range_right
+ 1;
3018 log_file_error(filename
, location
.first_line
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
3020 // $size(), $left(), $right(), $high(), $low()
3022 if (mem_range
->type
== AST_RANGE
) {
3023 if (id_ast
->multirange_dimensions
.empty()) {
3024 if (!mem_range
->range_valid
)
3025 log_file_error(filename
, location
.first_line
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
3027 left
= mem_range
->range_right
;
3028 right
= mem_range
->range_left
;
3029 high
= max(left
, right
);
3030 low
= min(left
, right
);
3033 dims
= GetSize(id_ast
->multirange_dimensions
)/2;
3035 width_hint
= id_ast
->multirange_dimensions
[2*dim
-1];
3036 high
= id_ast
->multirange_dimensions
[2*dim
-2] + id_ast
->multirange_dimensions
[2*dim
-1] - 1;
3037 low
= id_ast
->multirange_dimensions
[2*dim
-2];
3038 if (id_ast
->multirange_swapped
[dim
-1]) {
3045 } else if ((dim
> dims
+1) || (dim
< 0))
3046 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);
3049 log_file_error(filename
, location
.first_line
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
3053 width
= high
- low
+ 1;
3058 if (str
== "\\$high")
3060 else if (str
== "\\$low")
3062 else if (str
== "\\$left")
3064 else if (str
== "\\$right")
3066 else if (str
== "\\$size")
3069 result
= width
* mem_depth
;
3071 newNode
= mkconst_int(result
, false);
3075 if (str
== "\\$ln" || str
== "\\$log10" || str
== "\\$exp" || str
== "\\$sqrt" || str
== "\\$pow" ||
3076 str
== "\\$floor" || str
== "\\$ceil" || str
== "\\$sin" || str
== "\\$cos" || str
== "\\$tan" ||
3077 str
== "\\$asin" || str
== "\\$acos" || str
== "\\$atan" || str
== "\\$atan2" || str
== "\\$hypot" ||
3078 str
== "\\$sinh" || str
== "\\$cosh" || str
== "\\$tanh" || str
== "\\$asinh" || str
== "\\$acosh" || str
== "\\$atanh" ||
3079 str
== "\\$rtoi" || str
== "\\$itor")
3081 bool func_with_two_arguments
= str
== "\\$pow" || str
== "\\$atan2" || str
== "\\$hypot";
3082 double x
= 0, y
= 0;
3084 if (func_with_two_arguments
) {
3085 if (children
.size() != 2)
3086 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 2.\n",
3087 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
3089 if (children
.size() != 1)
3090 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
3091 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
3094 if (children
.size() >= 1) {
3095 while (children
[0]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
3096 if (!children
[0]->isConst())
3097 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant argument.\n",
3098 RTLIL::unescape_id(str
).c_str());
3099 int child_width_hint
= width_hint
;
3100 bool child_sign_hint
= sign_hint
;
3101 children
[0]->detectSignWidth(child_width_hint
, child_sign_hint
);
3102 x
= children
[0]->asReal(child_sign_hint
);
3105 if (children
.size() >= 2) {
3106 while (children
[1]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
3107 if (!children
[1]->isConst())
3108 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant argument.\n",
3109 RTLIL::unescape_id(str
).c_str());
3110 int child_width_hint
= width_hint
;
3111 bool child_sign_hint
= sign_hint
;
3112 children
[1]->detectSignWidth(child_width_hint
, child_sign_hint
);
3113 y
= children
[1]->asReal(child_sign_hint
);
3116 if (str
== "\\$rtoi") {
3117 newNode
= AstNode::mkconst_int(x
, true);
3119 newNode
= new AstNode(AST_REALVALUE
);
3120 if (str
== "\\$ln") newNode
->realvalue
= ::log(x
);
3121 else if (str
== "\\$log10") newNode
->realvalue
= ::log10(x
);
3122 else if (str
== "\\$exp") newNode
->realvalue
= ::exp(x
);
3123 else if (str
== "\\$sqrt") newNode
->realvalue
= ::sqrt(x
);
3124 else if (str
== "\\$pow") newNode
->realvalue
= ::pow(x
, y
);
3125 else if (str
== "\\$floor") newNode
->realvalue
= ::floor(x
);
3126 else if (str
== "\\$ceil") newNode
->realvalue
= ::ceil(x
);
3127 else if (str
== "\\$sin") newNode
->realvalue
= ::sin(x
);
3128 else if (str
== "\\$cos") newNode
->realvalue
= ::cos(x
);
3129 else if (str
== "\\$tan") newNode
->realvalue
= ::tan(x
);
3130 else if (str
== "\\$asin") newNode
->realvalue
= ::asin(x
);
3131 else if (str
== "\\$acos") newNode
->realvalue
= ::acos(x
);
3132 else if (str
== "\\$atan") newNode
->realvalue
= ::atan(x
);
3133 else if (str
== "\\$atan2") newNode
->realvalue
= ::atan2(x
, y
);
3134 else if (str
== "\\$hypot") newNode
->realvalue
= ::hypot(x
, y
);
3135 else if (str
== "\\$sinh") newNode
->realvalue
= ::sinh(x
);
3136 else if (str
== "\\$cosh") newNode
->realvalue
= ::cosh(x
);
3137 else if (str
== "\\$tanh") newNode
->realvalue
= ::tanh(x
);
3138 else if (str
== "\\$asinh") newNode
->realvalue
= ::asinh(x
);
3139 else if (str
== "\\$acosh") newNode
->realvalue
= ::acosh(x
);
3140 else if (str
== "\\$atanh") newNode
->realvalue
= ::atanh(x
);
3141 else if (str
== "\\$itor") newNode
->realvalue
= x
;
3147 if (str
== "\\$sformatf") {
3148 AstNode
*node_string
= children
[0];
3149 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
3150 if (node_string
->type
!= AST_CONSTANT
)
3151 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
3152 std::string sformat
= node_string
->bitsAsConst().decode_string();
3153 std::string sout
= process_format_str(sformat
, 1, stage
, width_hint
, sign_hint
);
3154 newNode
= AstNode::mkconst_str(sout
);
3158 if (str
== "\\$countbits") {
3159 if (children
.size() < 2)
3160 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected at least 2.\n",
3161 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
3163 std::vector
<RTLIL::State
> control_bits
;
3165 // Determine which bits to count
3166 for (size_t i
= 1; i
< children
.size(); i
++) {
3167 AstNode
*node
= children
[i
];
3168 while (node
->simplify(true, false, false, stage
, -1, false, false)) { }
3169 if (node
->type
!= AST_CONSTANT
)
3170 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant control bit argument.\n", str
.c_str());
3171 if (node
->bits
.size() != 1)
3172 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with control bit width != 1.\n", str
.c_str());
3173 control_bits
.push_back(node
->bits
[0]);
3176 // Detect width of exp (first argument of $countbits)
3178 bool exp_sign
= false;
3179 AstNode
*exp
= children
[0];
3180 exp
->detectSignWidth(exp_width
, exp_sign
, NULL
);
3182 newNode
= mkconst_int(0, false);
3184 for (int i
= 0; i
< exp_width
; i
++) {
3185 // Generate nodes for: exp << i >> ($size(exp) - 1)
3187 AstNode
*lsh_node
= new AstNode(AST_SHIFT_LEFT
, exp
->clone(), mkconst_int(i
, false));
3188 AstNode
*rsh_node
= new AstNode(AST_SHIFT_RIGHT
, lsh_node
, mkconst_int(exp_width
- 1, false));
3190 AstNode
*or_node
= nullptr;
3192 for (RTLIL::State control_bit
: control_bits
) {
3193 // Generate node for: (exp << i >> ($size(exp) - 1)) === control_bit
3195 AstNode
*eq_node
= new AstNode(AST_EQX
, rsh_node
->clone(), mkconst_bits({control_bit
}, false));
3197 // Or the result for each checked bit value
3199 or_node
= new AstNode(AST_LOGIC_OR
, or_node
, eq_node
);
3204 // We should have at least one element in control_bits,
3205 // because we checked for the number of arguments above
3206 log_assert(or_node
!= nullptr);
3210 // Generate node for adding with result of previous bit
3211 newNode
= new AstNode(AST_ADD
, newNode
, or_node
);
3217 if (str
== "\\$countones" || str
== "\\$isunknown" || str
== "\\$onehot" || str
== "\\$onehot0") {
3218 if (children
.size() != 1)
3219 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
3220 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
3222 AstNode
*countbits
= clone();
3223 countbits
->str
= "\\$countbits";
3225 if (str
== "\\$countones") {
3226 countbits
->children
.push_back(mkconst_bits({RTLIL::State::S1
}, false));
3227 newNode
= countbits
;
3228 } else if (str
== "\\$isunknown") {
3229 countbits
->children
.push_back(mkconst_bits({RTLIL::Sx
}, false));
3230 countbits
->children
.push_back(mkconst_bits({RTLIL::Sz
}, false));
3231 newNode
= new AstNode(AST_GT
, countbits
, mkconst_int(0, false));
3232 } else if (str
== "\\$onehot") {
3233 countbits
->children
.push_back(mkconst_bits({RTLIL::State::S1
}, false));
3234 newNode
= new AstNode(AST_EQ
, countbits
, mkconst_int(1, false));
3235 } else if (str
== "\\$onehot0") {
3236 countbits
->children
.push_back(mkconst_bits({RTLIL::State::S1
}, false));
3237 newNode
= new AstNode(AST_LE
, countbits
, mkconst_int(1, false));
3245 if (current_scope
.count(str
) != 0 && current_scope
[str
]->type
== AST_DPI_FUNCTION
)
3247 AstNode
*dpi_decl
= current_scope
[str
];
3249 std::string rtype
, fname
;
3250 std::vector
<std::string
> argtypes
;
3251 std::vector
<AstNode
*> args
;
3253 rtype
= RTLIL::unescape_id(dpi_decl
->children
.at(0)->str
);
3254 fname
= RTLIL::unescape_id(dpi_decl
->children
.at(1)->str
);
3256 for (int i
= 2; i
< GetSize(dpi_decl
->children
); i
++)
3258 if (i
-2 >= GetSize(children
))
3259 log_file_error(filename
, location
.first_line
, "Insufficient number of arguments in DPI function call.\n");
3261 argtypes
.push_back(RTLIL::unescape_id(dpi_decl
->children
.at(i
)->str
));
3262 args
.push_back(children
.at(i
-2)->clone());
3263 while (args
.back()->simplify(true, false, false, stage
, -1, false, true)) { }
3265 if (args
.back()->type
!= AST_CONSTANT
&& args
.back()->type
!= AST_REALVALUE
)
3266 log_file_error(filename
, location
.first_line
, "Failed to evaluate DPI function with non-constant argument.\n");
3269 newNode
= dpi_call(rtype
, fname
, argtypes
, args
);
3271 for (auto arg
: args
)
3277 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_FUNCTION
)
3278 log_file_error(filename
, location
.first_line
, "Can't resolve function name `%s'.\n", str
.c_str());
3281 if (type
== AST_TCALL
)
3283 if (str
== "$finish" || str
== "$stop")
3285 if (!current_always
|| current_always
->type
!= AST_INITIAL
)
3286 log_file_error(filename
, location
.first_line
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
3288 log_file_error(filename
, location
.first_line
, "System task `%s' executed.\n", str
.c_str());
3291 if (str
== "\\$readmemh" || str
== "\\$readmemb")
3293 if (GetSize(children
) < 2 || GetSize(children
) > 4)
3294 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 2-4.\n",
3295 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
3297 AstNode
*node_filename
= children
[0]->clone();
3298 while (node_filename
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
3299 if (node_filename
->type
!= AST_CONSTANT
)
3300 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
3302 AstNode
*node_memory
= children
[1]->clone();
3303 while (node_memory
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
3304 if (node_memory
->type
!= AST_IDENTIFIER
|| node_memory
->id2ast
== nullptr || node_memory
->id2ast
->type
!= AST_MEMORY
)
3305 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str
.c_str());
3307 int start_addr
= -1, finish_addr
= -1;
3309 if (GetSize(children
) > 2) {
3310 AstNode
*node_addr
= children
[2]->clone();
3311 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
3312 if (node_addr
->type
!= AST_CONSTANT
)
3313 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str
.c_str());
3314 start_addr
= int(node_addr
->asInt(false));
3317 if (GetSize(children
) > 3) {
3318 AstNode
*node_addr
= children
[3]->clone();
3319 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
3320 if (node_addr
->type
!= AST_CONSTANT
)
3321 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str
.c_str());
3322 finish_addr
= int(node_addr
->asInt(false));
3325 bool unconditional_init
= false;
3326 if (current_always
->type
== AST_INITIAL
) {
3327 pool
<AstNode
*> queue
;
3328 log_assert(current_always
->children
[0]->type
== AST_BLOCK
);
3329 queue
.insert(current_always
->children
[0]);
3330 while (!unconditional_init
&& !queue
.empty()) {
3331 pool
<AstNode
*> next_queue
;
3332 for (auto n
: queue
)
3333 for (auto c
: n
->children
) {
3335 unconditional_init
= true;
3336 next_queue
.insert(c
);
3338 next_queue
.swap(queue
);
3342 newNode
= readmem(str
== "\\$readmemh", node_filename
->bitsAsConst().decode_string(), node_memory
->id2ast
, start_addr
, finish_addr
, unconditional_init
);
3343 delete node_filename
;
3348 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_TASK
)
3349 log_file_error(filename
, location
.first_line
, "Can't resolve task name `%s'.\n", str
.c_str());
3353 std::stringstream sstr
;
3354 sstr
<< str
<< "$func$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++) << '.';
3355 std::string prefix
= sstr
.str();
3357 AstNode
*decl
= current_scope
[str
];
3358 if (unevaluated_tern_branch
&& decl
->is_recursive_function())
3359 goto replace_fcall_later
;
3360 decl
= decl
->clone();
3361 decl
->replace_result_wire_name_in_function(str
, "$result"); // enables recursion
3362 decl
->expand_genblock(prefix
);
3364 if (decl
->type
== AST_FUNCTION
&& !decl
->attributes
.count(ID::via_celltype
))
3366 bool require_const_eval
= decl
->has_const_only_constructs();
3367 bool all_args_const
= true;
3368 for (auto child
: children
) {
3369 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
3370 if (child
->type
!= AST_CONSTANT
&& child
->type
!= AST_REALVALUE
)
3371 all_args_const
= false;
3374 if (all_args_const
) {
3375 AstNode
*func_workspace
= decl
->clone();
3376 func_workspace
->str
= prefix_id(prefix
, "$result");
3377 newNode
= func_workspace
->eval_const_function(this, in_param
|| require_const_eval
);
3378 delete func_workspace
;
3386 log_file_error(filename
, location
.first_line
, "Non-constant function call in constant expression.\n");
3387 if (require_const_eval
)
3388 log_file_error(filename
, location
.first_line
, "Function %s can only be called with constant arguments.\n", str
.c_str());
3391 size_t arg_count
= 0;
3392 dict
<std::string
, AstNode
*> wire_cache
;
3393 vector
<AstNode
*> new_stmts
;
3394 vector
<AstNode
*> output_assignments
;
3396 if (current_block
== NULL
)
3398 log_assert(type
== AST_FCALL
);
3400 AstNode
*wire
= NULL
;
3401 std::string res_name
= prefix_id(prefix
, "$result");
3402 for (auto child
: decl
->children
)
3403 if (child
->type
== AST_WIRE
&& child
->str
== res_name
)
3404 wire
= child
->clone();
3405 log_assert(wire
!= NULL
);
3408 wire
->is_input
= false;
3409 wire
->is_output
= false;
3411 current_scope
[wire
->str
] = wire
;
3412 current_ast_mod
->children
.push_back(wire
);
3413 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
3415 AstNode
*lvalue
= new AstNode(AST_IDENTIFIER
);
3416 lvalue
->str
= wire
->str
;
3418 AstNode
*always
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
,
3419 new AstNode(AST_ASSIGN_EQ
, lvalue
, clone())));
3420 always
->children
[0]->children
[0]->was_checked
= true;
3422 current_ast_mod
->children
.push_back(always
);
3424 goto replace_fcall_with_id
;
3427 if (decl
->attributes
.count(ID::via_celltype
))
3429 std::string celltype
= decl
->attributes
.at(ID::via_celltype
)->asAttrConst().decode_string();
3430 std::string outport
= str
;
3432 if (celltype
.find(' ') != std::string::npos
) {
3433 int pos
= celltype
.find(' ');
3434 outport
= RTLIL::escape_id(celltype
.substr(pos
+1));
3435 celltype
= RTLIL::escape_id(celltype
.substr(0, pos
));
3437 celltype
= RTLIL::escape_id(celltype
);
3439 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
));
3440 cell
->str
= prefix
.substr(0, GetSize(prefix
)-1);
3441 cell
->children
[0]->str
= celltype
;
3443 for (auto attr
: decl
->attributes
)
3444 if (attr
.first
.str().rfind("\\via_celltype_defparam_", 0) == 0)
3446 AstNode
*cell_arg
= new AstNode(AST_PARASET
, attr
.second
->clone());
3447 cell_arg
->str
= RTLIL::escape_id(attr
.first
.substr(strlen("\\via_celltype_defparam_")));
3448 cell
->children
.push_back(cell_arg
);
3451 for (auto child
: decl
->children
)
3452 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
|| (type
== AST_FCALL
&& child
->str
== str
)))
3454 AstNode
*wire
= child
->clone();
3456 wire
->is_input
= false;
3457 wire
->is_output
= false;
3458 current_ast_mod
->children
.push_back(wire
);
3459 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
3461 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
3462 wire_id
->str
= wire
->str
;
3464 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
3466 AstNode
*arg
= children
[arg_count
++]->clone();
3467 AstNode
*assign
= child
->is_input
?
3468 new AstNode(AST_ASSIGN_EQ
, wire_id
->clone(), arg
) :
3469 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
->clone());
3470 assign
->children
[0]->was_checked
= true;
3472 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
3473 if (*it
!= current_block_child
)
3475 current_block
->children
.insert(it
, assign
);
3480 AstNode
*cell_arg
= new AstNode(AST_ARGUMENT
, wire_id
);
3481 cell_arg
->str
= child
->str
== str
? outport
: child
->str
;
3482 cell
->children
.push_back(cell_arg
);
3485 current_ast_mod
->children
.push_back(cell
);
3486 goto replace_fcall_with_id
;
3489 for (auto child
: decl
->children
)
3490 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
|| child
->type
== AST_ENUM_ITEM
)
3492 AstNode
*wire
= nullptr;
3494 if (wire_cache
.count(child
->str
))
3496 wire
= wire_cache
.at(child
->str
);
3497 bool contains_value
= wire
->type
== AST_LOCALPARAM
;
3498 if (wire
->children
.size() == contains_value
) {
3499 for (auto c
: child
->children
)
3500 wire
->children
.push_back(c
->clone());
3501 } else if (!child
->children
.empty()) {
3502 while (child
->simplify(true, false, false, stage
, -1, false, false)) { }
3503 if (GetSize(child
->children
) == GetSize(wire
->children
) - contains_value
) {
3504 for (int i
= 0; i
< GetSize(child
->children
); i
++)
3505 if (*child
->children
.at(i
) != *wire
->children
.at(i
+ contains_value
))
3506 goto tcall_incompatible_wires
;
3508 tcall_incompatible_wires
:
3509 log_file_error(filename
, location
.first_line
, "Incompatible re-declaration of wire %s.\n", child
->str
.c_str());
3515 wire
= child
->clone();
3517 wire
->is_input
= false;
3518 wire
->is_output
= false;
3519 wire
->is_reg
= true;
3520 wire
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
3521 if (child
->type
== AST_ENUM_ITEM
)
3522 wire
->attributes
[ID::enum_base_type
] = child
->attributes
[ID::enum_base_type
];
3524 wire_cache
[child
->str
] = wire
;
3526 current_scope
[wire
->str
] = wire
;
3527 current_ast_mod
->children
.push_back(wire
);
3530 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
3532 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
3534 AstNode
*arg
= children
[arg_count
++]->clone();
3535 // convert purely constant arguments into localparams
3536 if (child
->is_input
&& child
->type
== AST_WIRE
&& arg
->type
== AST_CONSTANT
&& node_contains_assignment_to(decl
, child
)) {
3537 wire
->type
= AST_LOCALPARAM
;
3538 if (wire
->attributes
.count(ID::nosync
))
3539 delete wire
->attributes
.at(ID::nosync
);
3540 wire
->attributes
.erase(ID::nosync
);
3541 wire
->children
.insert(wire
->children
.begin(), arg
->clone());
3542 // args without a range implicitly have width 1
3543 if (wire
->children
.back()->type
!= AST_RANGE
) {
3544 // check if this wire is redeclared with an explicit size
3545 bool uses_explicit_size
= false;
3546 for (const AstNode
*other_child
: decl
->children
)
3547 if (other_child
->type
== AST_WIRE
&& child
->str
== other_child
->str
3548 && !other_child
->children
.empty()
3549 && other_child
->children
.back()->type
== AST_RANGE
) {
3550 uses_explicit_size
= true;
3553 if (!uses_explicit_size
) {
3554 AstNode
* range
= new AstNode();
3555 range
->type
= AST_RANGE
;
3556 wire
->children
.push_back(range
);
3557 range
->children
.push_back(mkconst_int(0, true));
3558 range
->children
.push_back(mkconst_int(0, true));
3561 // updates the sizing
3562 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
3566 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
3567 wire_id
->str
= wire
->str
;
3568 AstNode
*assign
= child
->is_input
?
3569 new AstNode(AST_ASSIGN_EQ
, wire_id
, arg
) :
3570 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
);
3571 assign
->children
[0]->was_checked
= true;
3572 if (child
->is_input
)
3573 new_stmts
.push_back(assign
);
3575 output_assignments
.push_back(assign
);
3579 for (auto child
: decl
->children
)
3580 if (child
->type
!= AST_WIRE
&& child
->type
!= AST_MEMORY
&& child
->type
!= AST_PARAMETER
&& child
->type
!= AST_LOCALPARAM
)
3581 new_stmts
.push_back(child
->clone());
3583 new_stmts
.insert(new_stmts
.end(), output_assignments
.begin(), output_assignments
.end());
3585 for (auto it
= current_block
->children
.begin(); ; it
++) {
3586 log_assert(it
!= current_block
->children
.end());
3587 if (*it
== current_block_child
) {
3588 current_block
->children
.insert(it
, new_stmts
.begin(), new_stmts
.end());
3593 replace_fcall_with_id
:
3595 if (type
== AST_FCALL
) {
3597 type
= AST_IDENTIFIER
;
3598 str
= prefix_id(prefix
, "$result");
3600 if (type
== AST_TCALL
)
3602 did_something
= true;
3605 replace_fcall_later
:;
3607 // perform const folding when activated
3611 std::vector
<RTLIL::State
> tmp_bits
;
3612 RTLIL::Const (*const_func
)(const RTLIL::Const
&, const RTLIL::Const
&, bool, bool, int);
3613 RTLIL::Const dummy_arg
;
3617 case AST_IDENTIFIER
:
3618 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
)) {
3619 if (current_scope
[str
]->children
[0]->type
== AST_CONSTANT
) {
3620 if (children
.size() != 0 && children
[0]->type
== AST_RANGE
&& children
[0]->range_valid
) {
3621 std::vector
<RTLIL::State
> data
;
3622 bool param_upto
= current_scope
[str
]->range_valid
&& current_scope
[str
]->range_swapped
;
3623 int param_offset
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_right
: 0;
3624 int param_width
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_left
- current_scope
[str
]->range_right
+ 1 :
3625 GetSize(current_scope
[str
]->children
[0]->bits
);
3626 int tmp_range_left
= children
[0]->range_left
, tmp_range_right
= children
[0]->range_right
;
3628 tmp_range_left
= (param_width
+ 2*param_offset
) - children
[0]->range_right
- 1;
3629 tmp_range_right
= (param_width
+ 2*param_offset
) - children
[0]->range_left
- 1;
3631 for (int i
= tmp_range_right
; i
<= tmp_range_left
; i
++) {
3632 int index
= i
- param_offset
;
3633 if (0 <= index
&& index
< param_width
)
3634 data
.push_back(current_scope
[str
]->children
[0]->bits
[index
]);
3636 data
.push_back(RTLIL::State::Sx
);
3638 newNode
= mkconst_bits(data
, false);
3640 if (children
.size() == 0)
3641 newNode
= current_scope
[str
]->children
[0]->clone();
3643 if (current_scope
[str
]->children
[0]->isConst())
3644 newNode
= current_scope
[str
]->children
[0]->clone();
3646 else if (at_zero
&& current_scope
.count(str
) > 0) {
3647 AstNode
*node
= current_scope
[str
];
3648 if (node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_MEMORY
)
3649 newNode
= mkconst_int(0, sign_hint
, width_hint
);
3654 newNode
= mkconst_int(0, sign_hint
, width_hint
);
3658 if (children
[0]->type
== AST_CONSTANT
) {
3659 RTLIL::Const y
= RTLIL::const_not(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
3660 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3664 case AST_TO_UNSIGNED
:
3665 if (children
[0]->type
== AST_CONSTANT
) {
3666 RTLIL::Const y
= children
[0]->bitsAsConst(width_hint
, sign_hint
);
3667 newNode
= mkconst_bits(y
.bits
, type
== AST_TO_SIGNED
);
3670 if (0) { case AST_BIT_AND
: const_func
= RTLIL::const_and
; }
3671 if (0) { case AST_BIT_OR
: const_func
= RTLIL::const_or
; }
3672 if (0) { case AST_BIT_XOR
: const_func
= RTLIL::const_xor
; }
3673 if (0) { case AST_BIT_XNOR
: const_func
= RTLIL::const_xnor
; }
3674 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3675 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3676 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
3677 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3680 if (0) { case AST_REDUCE_AND
: const_func
= RTLIL::const_reduce_and
; }
3681 if (0) { case AST_REDUCE_OR
: const_func
= RTLIL::const_reduce_or
; }
3682 if (0) { case AST_REDUCE_XOR
: const_func
= RTLIL::const_reduce_xor
; }
3683 if (0) { case AST_REDUCE_XNOR
: const_func
= RTLIL::const_reduce_xnor
; }
3684 if (0) { case AST_REDUCE_BOOL
: const_func
= RTLIL::const_reduce_bool
; }
3685 if (children
[0]->type
== AST_CONSTANT
) {
3686 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), dummy_arg
, false, false, -1);
3687 newNode
= mkconst_bits(y
.bits
, false);
3691 if (children
[0]->type
== AST_CONSTANT
) {
3692 RTLIL::Const y
= RTLIL::const_logic_not(RTLIL::Const(children
[0]->bits
), dummy_arg
, children
[0]->is_signed
, false, -1);
3693 newNode
= mkconst_bits(y
.bits
, false);
3695 if (children
[0]->isConst()) {
3696 newNode
= mkconst_int(children
[0]->asReal(sign_hint
) == 0, false, 1);
3699 if (0) { case AST_LOGIC_AND
: const_func
= RTLIL::const_logic_and
; }
3700 if (0) { case AST_LOGIC_OR
: const_func
= RTLIL::const_logic_or
; }
3701 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3702 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), RTLIL::Const(children
[1]->bits
),
3703 children
[0]->is_signed
, children
[1]->is_signed
, -1);
3704 newNode
= mkconst_bits(y
.bits
, false);
3706 if (children
[0]->isConst() && children
[1]->isConst()) {
3707 if (type
== AST_LOGIC_AND
)
3708 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) && (children
[1]->asReal(sign_hint
) != 0), false, 1);
3710 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) || (children
[1]->asReal(sign_hint
) != 0), false, 1);
3713 if (0) { case AST_SHIFT_LEFT
: const_func
= RTLIL::const_shl
; }
3714 if (0) { case AST_SHIFT_RIGHT
: const_func
= RTLIL::const_shr
; }
3715 if (0) { case AST_SHIFT_SLEFT
: const_func
= RTLIL::const_sshl
; }
3716 if (0) { case AST_SHIFT_SRIGHT
: const_func
= RTLIL::const_sshr
; }
3717 if (0) { case AST_POW
: const_func
= RTLIL::const_pow
; }
3718 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3719 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3720 RTLIL::Const(children
[1]->bits
), sign_hint
, type
== AST_POW
? children
[1]->is_signed
: false, width_hint
);
3721 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3723 if (type
== AST_POW
&& children
[0]->isConst() && children
[1]->isConst()) {
3724 newNode
= new AstNode(AST_REALVALUE
);
3725 newNode
->realvalue
= pow(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
));
3728 if (0) { case AST_LT
: const_func
= RTLIL::const_lt
; }
3729 if (0) { case AST_LE
: const_func
= RTLIL::const_le
; }
3730 if (0) { case AST_EQ
: const_func
= RTLIL::const_eq
; }
3731 if (0) { case AST_NE
: const_func
= RTLIL::const_ne
; }
3732 if (0) { case AST_EQX
: const_func
= RTLIL::const_eqx
; }
3733 if (0) { case AST_NEX
: const_func
= RTLIL::const_nex
; }
3734 if (0) { case AST_GE
: const_func
= RTLIL::const_ge
; }
3735 if (0) { case AST_GT
: const_func
= RTLIL::const_gt
; }
3736 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3737 int cmp_width
= max(children
[0]->bits
.size(), children
[1]->bits
.size());
3738 bool cmp_signed
= children
[0]->is_signed
&& children
[1]->is_signed
;
3739 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(cmp_width
, cmp_signed
),
3740 children
[1]->bitsAsConst(cmp_width
, cmp_signed
), cmp_signed
, cmp_signed
, 1);
3741 newNode
= mkconst_bits(y
.bits
, false);
3743 if (children
[0]->isConst() && children
[1]->isConst()) {
3744 bool cmp_signed
= (children
[0]->type
== AST_REALVALUE
|| children
[0]->is_signed
) && (children
[1]->type
== AST_REALVALUE
|| children
[1]->is_signed
);
3746 case AST_LT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) < children
[1]->asReal(cmp_signed
), false, 1); break;
3747 case AST_LE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) <= children
[1]->asReal(cmp_signed
), false, 1); break;
3748 case AST_EQ
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
3749 case AST_NE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
3750 case AST_EQX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
3751 case AST_NEX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
3752 case AST_GE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) >= children
[1]->asReal(cmp_signed
), false, 1); break;
3753 case AST_GT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) > children
[1]->asReal(cmp_signed
), false, 1); break;
3754 default: log_abort();
3758 if (0) { case AST_ADD
: const_func
= RTLIL::const_add
; }
3759 if (0) { case AST_SUB
: const_func
= RTLIL::const_sub
; }
3760 if (0) { case AST_MUL
: const_func
= RTLIL::const_mul
; }
3761 if (0) { case AST_DIV
: const_func
= RTLIL::const_div
; }
3762 if (0) { case AST_MOD
: const_func
= RTLIL::const_mod
; }
3763 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3764 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3765 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
3766 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3768 if (children
[0]->isConst() && children
[1]->isConst()) {
3769 newNode
= new AstNode(AST_REALVALUE
);
3771 case AST_ADD
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) + children
[1]->asReal(sign_hint
); break;
3772 case AST_SUB
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) - children
[1]->asReal(sign_hint
); break;
3773 case AST_MUL
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) * children
[1]->asReal(sign_hint
); break;
3774 case AST_DIV
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) / children
[1]->asReal(sign_hint
); break;
3775 case AST_MOD
: newNode
->realvalue
= fmod(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
)); break;
3776 default: log_abort();
3780 if (0) { case AST_SELFSZ
: const_func
= RTLIL::const_pos
; }
3781 if (0) { case AST_POS
: const_func
= RTLIL::const_pos
; }
3782 if (0) { case AST_NEG
: const_func
= RTLIL::const_neg
; }
3783 if (children
[0]->type
== AST_CONSTANT
) {
3784 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
3785 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3787 if (children
[0]->isConst()) {
3788 newNode
= new AstNode(AST_REALVALUE
);
3789 if (type
== AST_NEG
)
3790 newNode
->realvalue
= -children
[0]->asReal(sign_hint
);
3792 newNode
->realvalue
= +children
[0]->asReal(sign_hint
);
3796 if (children
[0]->isConst())
3798 auto pair
= get_tern_choice();
3799 AstNode
*choice
= pair
.first
;
3800 AstNode
*not_choice
= pair
.second
;
3802 if (choice
!= NULL
) {
3803 if (choice
->type
== AST_CONSTANT
) {
3804 int other_width_hint
= width_hint
;
3805 bool other_sign_hint
= sign_hint
, other_real
= false;
3806 not_choice
->detectSignWidth(other_width_hint
, other_sign_hint
, &other_real
);
3808 newNode
= new AstNode(AST_REALVALUE
);
3809 choice
->detectSignWidth(width_hint
, sign_hint
);
3810 newNode
->realvalue
= choice
->asReal(sign_hint
);
3812 RTLIL::Const y
= choice
->bitsAsConst(width_hint
, sign_hint
);
3813 if (choice
->is_string
&& y
.bits
.size() % 8 == 0 && sign_hint
== false)
3814 newNode
= mkconst_str(y
.bits
);
3816 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3819 if (choice
->isConst()) {
3820 newNode
= choice
->clone();
3822 } else if (children
[1]->type
== AST_CONSTANT
&& children
[2]->type
== AST_CONSTANT
) {
3823 RTLIL::Const a
= children
[1]->bitsAsConst(width_hint
, sign_hint
);
3824 RTLIL::Const b
= children
[2]->bitsAsConst(width_hint
, sign_hint
);
3825 log_assert(a
.bits
.size() == b
.bits
.size());
3826 for (size_t i
= 0; i
< a
.bits
.size(); i
++)
3827 if (a
.bits
[i
] != b
.bits
[i
])
3828 a
.bits
[i
] = RTLIL::State::Sx
;
3829 newNode
= mkconst_bits(a
.bits
, sign_hint
);
3830 } else if (children
[1]->isConst() && children
[2]->isConst()) {
3831 newNode
= new AstNode(AST_REALVALUE
);
3832 if (children
[1]->asReal(sign_hint
) == children
[2]->asReal(sign_hint
))
3833 newNode
->realvalue
= children
[1]->asReal(sign_hint
);
3835 // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
3836 // the data type in question should be returned if the ?: is ambiguous. The
3837 // value in Table 7-1 for the 'real' type is 0.0.
3838 newNode
->realvalue
= 0.0;
3843 if (children
.at(0)->type
== AST_CONSTANT
&& children
.at(1)->type
== AST_CONSTANT
) {
3844 int width
= children
[0]->bitsAsConst().as_int();
3846 if (children
[1]->is_unsized
)
3847 val
= children
[1]->bitsAsUnsizedConst(width
);
3849 val
= children
[1]->bitsAsConst(width
);
3850 newNode
= mkconst_bits(val
.bits
, children
[1]->is_signed
);
3854 string_op
= !children
.empty();
3855 for (auto it
= children
.begin(); it
!= children
.end(); it
++) {
3856 if ((*it
)->type
!= AST_CONSTANT
)
3858 if (!(*it
)->is_string
)
3860 tmp_bits
.insert(tmp_bits
.end(), (*it
)->bits
.begin(), (*it
)->bits
.end());
3862 newNode
= string_op
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
3865 if (children
.at(0)->type
!= AST_CONSTANT
|| children
.at(1)->type
!= AST_CONSTANT
)
3867 for (int i
= 0; i
< children
[0]->bitsAsConst().as_int(); i
++)
3868 tmp_bits
.insert(tmp_bits
.end(), children
.at(1)->bits
.begin(), children
.at(1)->bits
.end());
3869 newNode
= children
.at(1)->is_string
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
3877 // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
3880 // fprintf(stderr, "----\n");
3881 // dumpAst(stderr, "- ");
3882 // newNode->dumpAst(stderr, "+ ");
3883 log_assert(newNode
!= NULL
);
3884 newNode
->filename
= filename
;
3885 newNode
->location
= location
;
3886 newNode
->cloneInto(this);
3888 did_something
= true;
3894 recursion_counter
--;
3895 return did_something
;
3898 void AstNode::replace_result_wire_name_in_function(const std::string
&from
, const std::string
&to
)
3900 for (AstNode
*child
: children
)
3901 child
->replace_result_wire_name_in_function(from
, to
);
3902 if (str
== from
&& type
!= AST_FCALL
&& type
!= AST_TCALL
)
3906 // replace a readmem[bh] TCALL ast node with a block of memory assignments
3907 AstNode
*AstNode::readmem(bool is_readmemh
, std::string mem_filename
, AstNode
*memory
, int start_addr
, int finish_addr
, bool unconditional_init
)
3909 int mem_width
, mem_size
, addr_bits
;
3910 memory
->meminfo(mem_width
, mem_size
, addr_bits
);
3912 AstNode
*block
= new AstNode(AST_BLOCK
);
3914 AstNode
*meminit
= nullptr;
3915 int next_meminit_cursor
=0;
3916 vector
<State
> meminit_bits
;
3917 vector
<State
> en_bits
;
3920 for (int i
= 0; i
< mem_width
; i
++)
3921 en_bits
.push_back(State::S1
);
3924 f
.open(mem_filename
.c_str());
3931 std::string path
= filename
.substr(0, filename
.find_last_of(slash
)+1);
3932 f
.open(path
+ mem_filename
.c_str());
3933 yosys_input_files
.insert(path
+ mem_filename
);
3935 yosys_input_files
.insert(mem_filename
);
3937 if (f
.fail() || GetSize(mem_filename
) == 0)
3938 log_file_error(filename
, location
.first_line
, "Can not open file `%s` for %s.\n", mem_filename
.c_str(), str
.c_str());
3940 log_assert(GetSize(memory
->children
) == 2 && memory
->children
[1]->type
== AST_RANGE
&& memory
->children
[1]->range_valid
);
3941 int range_left
= memory
->children
[1]->range_left
, range_right
= memory
->children
[1]->range_right
;
3942 int range_min
= min(range_left
, range_right
), range_max
= max(range_left
, range_right
);
3945 start_addr
= range_min
;
3947 if (finish_addr
< 0)
3948 finish_addr
= range_max
+ 1;
3950 bool in_comment
= false;
3951 int increment
= start_addr
<= finish_addr
? +1 : -1;
3952 int cursor
= start_addr
;
3956 std::string line
, token
;
3957 std::getline(f
, line
);
3959 for (int i
= 0; i
< GetSize(line
); i
++) {
3960 if (in_comment
&& line
.compare(i
, 2, "*/") == 0) {
3966 if (!in_comment
&& line
.compare(i
, 2, "/*") == 0)
3974 token
= next_token(line
, " \t\r\n");
3975 if (token
.empty() || token
.compare(0, 2, "//") == 0)
3978 if (token
[0] == '@') {
3979 token
= token
.substr(1);
3980 const char *nptr
= token
.c_str();
3982 cursor
= strtol(nptr
, &endptr
, 16);
3983 if (!*nptr
|| *endptr
)
3984 log_file_error(filename
, location
.first_line
, "Can not parse address `%s` for %s.\n", nptr
, str
.c_str());
3988 AstNode
*value
= VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width
, is_readmemh
? 'h' : 'b') + token
);
3990 if (unconditional_init
)
3992 if (meminit
== nullptr || cursor
!= next_meminit_cursor
)
3994 if (meminit
!= nullptr) {
3995 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
3996 meminit
->children
[3] = AstNode::mkconst_int(meminit_size
, false);
3999 meminit
= new AstNode(AST_MEMINIT
);
4000 meminit
->children
.push_back(AstNode::mkconst_int(cursor
, false));
4001 meminit
->children
.push_back(nullptr);
4002 meminit
->children
.push_back(AstNode::mkconst_bits(en_bits
, false));
4003 meminit
->children
.push_back(nullptr);
4004 meminit
->str
= memory
->str
;
4005 meminit
->id2ast
= memory
;
4006 meminit_bits
.clear();
4009 current_ast_mod
->children
.push_back(meminit
);
4010 next_meminit_cursor
= cursor
;
4014 next_meminit_cursor
++;
4015 meminit_bits
.insert(meminit_bits
.end(), value
->bits
.begin(), value
->bits
.end());
4020 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
, false))), value
));
4021 block
->children
.back()->children
[0]->str
= memory
->str
;
4022 block
->children
.back()->children
[0]->id2ast
= memory
;
4023 block
->children
.back()->children
[0]->was_checked
= true;
4026 cursor
+= increment
;
4027 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
4031 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
4035 if (meminit
!= nullptr) {
4036 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
4037 meminit
->children
[3] = AstNode::mkconst_int(meminit_size
, false);
4043 // annotate the names of all wires and other named objects in a named generate
4044 // or procedural block; nested blocks are themselves annotated such that the
4045 // prefix is carried forward, but resolution of their children is deferred
4046 void AstNode::expand_genblock(const std::string
&prefix
)
4048 if (type
== AST_IDENTIFIER
|| type
== AST_FCALL
|| type
== AST_TCALL
|| type
== AST_WIRETYPE
|| type
== AST_PREFIX
) {
4049 log_assert(!str
.empty());
4051 // search starting in the innermost scope and then stepping outward
4052 for (size_t ppos
= prefix
.size() - 1; ppos
; --ppos
) {
4053 if (prefix
.at(ppos
) != '.') continue;
4055 std::string new_prefix
= prefix
.substr(0, ppos
+ 1);
4056 auto attempt_resolve
= [&new_prefix
](const std::string
&ident
) -> std::string
{
4057 std::string new_name
= prefix_id(new_prefix
, ident
);
4058 if (current_scope
.count(new_name
))
4063 // attempt to resolve the full identifier
4064 std::string resolved
= attempt_resolve(str
);
4065 if (!resolved
.empty()) {
4070 // attempt to resolve hierarchical prefixes within the identifier,
4071 // as the prefix could refer to a local scope which exists but
4072 // hasn't yet been elaborated
4073 for (size_t spos
= str
.size() - 1; spos
; --spos
) {
4074 if (str
.at(spos
) != '.') continue;
4075 resolved
= attempt_resolve(str
.substr(0, spos
));
4076 if (!resolved
.empty()) {
4077 str
= resolved
+ str
.substr(spos
);
4078 ppos
= 1; // break outer loop
4086 auto prefix_node
= [&prefix
](AstNode
* child
) {
4087 if (child
->str
.empty()) return;
4088 std::string new_name
= prefix_id(prefix
, child
->str
);
4089 if (child
->type
== AST_FUNCTION
)
4090 child
->replace_result_wire_name_in_function(child
->str
, new_name
);
4092 child
->str
= new_name
;
4093 current_scope
[new_name
] = child
;
4096 for (size_t i
= 0; i
< children
.size(); i
++) {
4097 AstNode
*child
= children
[i
];
4099 switch (child
->type
) {
4103 case AST_LOCALPARAM
:
4115 if (!child
->str
.empty())
4120 current_scope
[child
->str
] = child
;
4121 for (auto enode
: child
->children
){
4122 log_assert(enode
->type
== AST_ENUM_ITEM
);
4132 for (size_t i
= 0; i
< children
.size(); i
++) {
4133 AstNode
*child
= children
[i
];
4134 // AST_PREFIX member names should not be prefixed; we recurse into them
4135 // as normal to ensure indices and ranges are properly resolved, and
4136 // then restore the previous string
4137 if (type
== AST_PREFIX
&& i
== 1) {
4138 std::string backup_scope_name
= child
->str
;
4139 child
->expand_genblock(prefix
);
4140 child
->str
= backup_scope_name
;
4143 // functions/tasks may reference wires, constants, etc. in this scope
4144 if (child
->type
== AST_FUNCTION
|| child
->type
== AST_TASK
)
4146 // named blocks pick up the current prefix and will expanded later
4147 if ((child
->type
== AST_GENBLOCK
|| child
->type
== AST_BLOCK
) && !child
->str
.empty())
4150 child
->expand_genblock(prefix
);
4154 // add implicit AST_GENBLOCK names according to IEEE 1364-2005 Section 12.4.3 or
4155 // IEEE 1800-2017 Section 27.6
4156 void AstNode::label_genblks(std::set
<std::string
>& existing
, int &counter
)
4162 // seeing a proper generate control flow construct increments the
4165 for (AstNode
*child
: children
)
4166 child
->label_genblks(existing
, counter
);
4169 case AST_GENBLOCK
: {
4170 // if this block is unlabeled, generate its corresponding unique name
4171 for (int padding
= 0; str
.empty(); ++padding
) {
4172 std::string candidate
= "\\genblk";
4173 for (int i
= 0; i
< padding
; ++i
)
4175 candidate
+= std::to_string(counter
);
4176 if (!existing
.count(candidate
))
4179 // within a genblk, the counter starts fresh
4180 std::set
<std::string
> existing_local
= existing
;
4181 int counter_local
= 0;
4182 for (AstNode
*child
: children
)
4183 child
->label_genblks(existing_local
, counter_local
);
4188 // track names which could conflict with implicit genblk names
4189 if (str
.rfind("\\genblk", 0) == 0)
4190 existing
.insert(str
);
4191 for (AstNode
*child
: children
)
4192 child
->label_genblks(existing
, counter
);
4197 // helper function for mem2reg_as_needed_pass1
4198 static void mark_memories_assign_lhs_complex(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
4199 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, AstNode
*that
)
4201 for (auto &child
: that
->children
)
4202 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, child
);
4204 if (that
->type
== AST_IDENTIFIER
&& that
->id2ast
&& that
->id2ast
->type
== AST_MEMORY
) {
4205 AstNode
*mem
= that
->id2ast
;
4206 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_CMPLX_LHS
))
4207 mem2reg_places
[mem
].insert(stringf("%s:%d", that
->filename
.c_str(), that
->location
.first_line
));
4208 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CMPLX_LHS
;
4212 // find memories that should be replaced by registers
4213 void AstNode::mem2reg_as_needed_pass1(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
4214 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, dict
<AstNode
*, uint32_t> &proc_flags
, uint32_t &flags
)
4216 uint32_t children_flags
= 0;
4217 int lhs_children_counter
= 0;
4219 if (type
== AST_TYPEDEF
)
4220 return; // don't touch content of typedefs
4222 if (type
== AST_ASSIGN
|| type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
)
4224 // mark all memories that are used in a complex expression on the left side of an assignment
4225 for (auto &lhs_child
: children
[0]->children
)
4226 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, lhs_child
);
4228 if (children
[0]->type
== AST_IDENTIFIER
&& children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
)
4230 AstNode
*mem
= children
[0]->id2ast
;
4232 // activate mem2reg if this is assigned in an async proc
4233 if (flags
& AstNode::MEM2REG_FL_ASYNC
) {
4234 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ASYNC
))
4235 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
4236 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ASYNC
;
4239 // remember if this is assigned blocking (=)
4240 if (type
== AST_ASSIGN_EQ
) {
4241 if (!(proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
))
4242 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
4243 proc_flags
[mem
] |= AstNode::MEM2REG_FL_EQ1
;
4246 // for proper (non-init) writes: remember if this is a constant index or not
4247 if ((flags
& MEM2REG_FL_INIT
) == 0) {
4248 if (children
[0]->children
.size() && children
[0]->children
[0]->type
== AST_RANGE
&& children
[0]->children
[0]->children
.size()) {
4249 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
)
4250 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CONST_LHS
;
4252 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_VAR_LHS
;
4256 // remember where this is
4257 if (flags
& MEM2REG_FL_INIT
) {
4258 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_INIT
))
4259 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
4260 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_INIT
;
4262 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ELSE
))
4263 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
4264 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ELSE
;
4268 lhs_children_counter
= 1;
4271 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
)
4273 AstNode
*mem
= id2ast
;
4275 // flag if used after blocking assignment (in same proc)
4276 if ((proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
) && !(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_EQ2
)) {
4277 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
4278 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_EQ2
;
4282 // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg' or 'logic'
4283 if (type
== AST_MEMORY
&& (get_bool_attribute(ID::mem2reg
) || (flags
& AstNode::MEM2REG_FL_ALL
) || !(is_reg
|| is_logic
)))
4284 mem2reg_candidates
[this] |= AstNode::MEM2REG_FL_FORCED
;
4286 if (type
== AST_MODULE
&& get_bool_attribute(ID::mem2reg
))
4287 children_flags
|= AstNode::MEM2REG_FL_ALL
;
4289 dict
<AstNode
*, uint32_t> *proc_flags_p
= NULL
;
4291 if (type
== AST_ALWAYS
) {
4292 int count_edge_events
= 0;
4293 for (auto child
: children
)
4294 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
4295 count_edge_events
++;
4296 if (count_edge_events
!= 1)
4297 children_flags
|= AstNode::MEM2REG_FL_ASYNC
;
4298 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
4301 if (type
== AST_INITIAL
) {
4302 children_flags
|= AstNode::MEM2REG_FL_INIT
;
4303 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
4306 uint32_t backup_flags
= flags
;
4307 flags
|= children_flags
;
4308 log_assert((flags
& ~0x000000ff) == 0);
4310 for (auto child
: children
)
4312 if (lhs_children_counter
> 0) {
4313 lhs_children_counter
--;
4314 if (child
->children
.size() && child
->children
[0]->type
== AST_RANGE
&& child
->children
[0]->children
.size()) {
4315 for (auto c
: child
->children
[0]->children
) {
4317 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
4319 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
4324 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
4326 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
4329 flags
&= ~children_flags
| backup_flags
;
4333 for (auto it
: *proc_flags_p
)
4334 log_assert((it
.second
& ~0xff000000) == 0);
4336 delete proc_flags_p
;
4340 bool AstNode::mem2reg_check(pool
<AstNode
*> &mem2reg_set
)
4342 if (type
!= AST_IDENTIFIER
|| !id2ast
|| !mem2reg_set
.count(id2ast
))
4345 if (children
.empty() || children
[0]->type
!= AST_RANGE
|| GetSize(children
[0]->children
) != 1)
4346 log_file_error(filename
, location
.first_line
, "Invalid array access.\n");
4351 void AstNode::mem2reg_remove(pool
<AstNode
*> &mem2reg_set
, vector
<AstNode
*> &delnodes
)
4353 log_assert(mem2reg_set
.count(this) == 0);
4355 if (mem2reg_set
.count(id2ast
))
4358 for (size_t i
= 0; i
< children
.size(); i
++) {
4359 if (mem2reg_set
.count(children
[i
]) > 0) {
4360 delnodes
.push_back(children
[i
]);
4361 children
.erase(children
.begin() + (i
--));
4363 children
[i
]->mem2reg_remove(mem2reg_set
, delnodes
);
4368 // actually replace memories with registers
4369 bool AstNode::mem2reg_as_needed_pass2(pool
<AstNode
*> &mem2reg_set
, AstNode
*mod
, AstNode
*block
, AstNode
*&async_block
)
4371 bool did_something
= false;
4373 if (type
== AST_BLOCK
)
4376 if (type
== AST_FUNCTION
|| type
== AST_TASK
)
4379 if (type
== AST_TYPEDEF
)
4382 if (type
== AST_MEMINIT
&& id2ast
&& mem2reg_set
.count(id2ast
))
4384 log_assert(children
[0]->type
== AST_CONSTANT
);
4385 log_assert(children
[1]->type
== AST_CONSTANT
);
4386 log_assert(children
[2]->type
== AST_CONSTANT
);
4387 log_assert(children
[3]->type
== AST_CONSTANT
);
4389 int cursor
= children
[0]->asInt(false);
4390 Const data
= children
[1]->bitsAsConst();
4391 Const en
= children
[2]->bitsAsConst();
4392 int length
= children
[3]->asInt(false);
4396 AstNode
*block
= new AstNode(AST_INITIAL
, new AstNode(AST_BLOCK
));
4397 mod
->children
.push_back(block
);
4398 block
= block
->children
[0];
4400 int wordsz
= GetSize(data
) / length
;
4402 for (int i
= 0; i
< length
; i
++) {
4404 while (pos
< wordsz
) {
4405 if (en
[pos
] != State::S1
) {
4409 while (epos
< wordsz
&& en
[epos
] == State::S1
)
4411 int clen
= epos
- pos
;
4412 AstNode
*range
= new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+i
, false));
4413 if (pos
!= 0 || epos
!= wordsz
) {
4416 AstNode
*mrange
= id2ast
->children
[0];
4417 if (mrange
->range_left
< mrange
->range_right
) {
4418 right
= mrange
->range_right
- pos
;
4419 left
= mrange
->range_right
- epos
+ 1;
4421 right
= mrange
->range_right
+ pos
;
4422 left
= mrange
->range_right
+ epos
- 1;
4424 range
= new AstNode(AST_MULTIRANGE
, range
, new AstNode(AST_RANGE
, AstNode::mkconst_int(left
, true), AstNode::mkconst_int(right
, true)));
4426 AstNode
*target
= new AstNode(AST_IDENTIFIER
, range
);
4428 target
->id2ast
= id2ast
;
4429 target
->was_checked
= true;
4430 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, target
, mkconst_bits(data
.extract(i
*wordsz
+ pos
, clen
).bits
, false)));
4437 AstNode
*newNode
= new AstNode(AST_NONE
);
4438 newNode
->cloneInto(this);
4441 did_something
= true;
4444 if (type
== AST_ASSIGN
&& block
== NULL
&& children
[0]->mem2reg_check(mem2reg_set
))
4446 if (async_block
== NULL
) {
4447 async_block
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
4448 mod
->children
.push_back(async_block
);
4451 AstNode
*newNode
= clone();
4452 newNode
->type
= AST_ASSIGN_EQ
;
4453 newNode
->children
[0]->was_checked
= true;
4454 async_block
->children
[0]->children
.push_back(newNode
);
4456 newNode
= new AstNode(AST_NONE
);
4457 newNode
->cloneInto(this);
4460 did_something
= true;
4463 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->mem2reg_check(mem2reg_set
) &&
4464 children
[0]->children
[0]->children
[0]->type
!= AST_CONSTANT
)
4466 std::stringstream sstr
;
4467 sstr
<< "$mem2reg_wr$" << children
[0]->str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
4468 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
4470 int mem_width
, mem_size
, addr_bits
;
4471 bool mem_signed
= children
[0]->id2ast
->is_signed
;
4472 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
4474 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
4475 wire_addr
->str
= id_addr
;
4476 wire_addr
->is_reg
= true;
4477 wire_addr
->was_checked
= true;
4478 wire_addr
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
4479 mod
->children
.push_back(wire_addr
);
4480 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
4482 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
4483 wire_data
->str
= id_data
;
4484 wire_data
->is_reg
= true;
4485 wire_data
->was_checked
= true;
4486 wire_data
->is_signed
= mem_signed
;
4487 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
4488 mod
->children
.push_back(wire_data
);
4489 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
4491 log_assert(block
!= NULL
);
4492 size_t assign_idx
= 0;
4493 while (assign_idx
< block
->children
.size() && block
->children
[assign_idx
] != this)
4495 log_assert(assign_idx
< block
->children
.size());
4497 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
4498 assign_addr
->children
[0]->str
= id_addr
;
4499 assign_addr
->children
[0]->was_checked
= true;
4500 block
->children
.insert(block
->children
.begin()+assign_idx
+1, assign_addr
);
4502 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
4503 case_node
->children
[0]->str
= id_addr
;
4504 for (int i
= 0; i
< mem_size
; i
++) {
4505 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->children
[0]->integer
) != i
)
4507 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
4508 AstNode
*assign_reg
= new AstNode(type
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
4509 if (children
[0]->children
.size() == 2)
4510 assign_reg
->children
[0]->children
.push_back(children
[0]->children
[1]->clone());
4511 assign_reg
->children
[0]->str
= stringf("%s[%d]", children
[0]->str
.c_str(), i
);
4512 assign_reg
->children
[1]->str
= id_data
;
4513 cond_node
->children
[1]->children
.push_back(assign_reg
);
4514 case_node
->children
.push_back(cond_node
);
4516 block
->children
.insert(block
->children
.begin()+assign_idx
+2, case_node
);
4518 children
[0]->delete_children();
4519 children
[0]->range_valid
= false;
4520 children
[0]->id2ast
= NULL
;
4521 children
[0]->str
= id_data
;
4522 type
= AST_ASSIGN_EQ
;
4523 children
[0]->was_checked
= true;
4525 did_something
= true;
4528 if (mem2reg_check(mem2reg_set
))
4530 AstNode
*bit_part_sel
= NULL
;
4531 if (children
.size() == 2)
4532 bit_part_sel
= children
[1]->clone();
4534 if (children
[0]->children
[0]->type
== AST_CONSTANT
)
4536 int id
= children
[0]->children
[0]->integer
;
4537 int left
= id2ast
->children
[1]->children
[0]->integer
;
4538 int right
= id2ast
->children
[1]->children
[1]->integer
;
4539 bool valid_const_access
=
4540 (left
<= id
&& id
<= right
) ||
4541 (right
<= id
&& id
<= left
);
4542 if (valid_const_access
)
4544 str
= stringf("%s[%d]", str
.c_str(), id
);
4546 range_valid
= false;
4554 bit_part_sel
->dumpAst(nullptr, "? ");
4555 if (bit_part_sel
->children
.size() == 1)
4558 width
= bit_part_sel
->children
[0]->integer
-
4559 bit_part_sel
->children
[1]->integer
;
4560 delete bit_part_sel
;
4561 bit_part_sel
= nullptr;
4565 width
= id2ast
->children
[0]->children
[0]->integer
-
4566 id2ast
->children
[0]->children
[1]->integer
;
4568 width
= abs(width
) + 1;
4572 std::vector
<RTLIL::State
> x_bits
;
4573 for (int i
= 0; i
< width
; i
++)
4574 x_bits
.push_back(RTLIL::State::Sx
);
4575 AstNode
*constant
= AstNode::mkconst_bits(x_bits
, false);
4576 constant
->cloneInto(this);
4582 std::stringstream sstr
;
4583 sstr
<< "$mem2reg_rd$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
4584 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
4586 int mem_width
, mem_size
, addr_bits
;
4587 bool mem_signed
= id2ast
->is_signed
;
4588 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
4590 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
4591 wire_addr
->str
= id_addr
;
4592 wire_addr
->is_reg
= true;
4593 wire_addr
->was_checked
= true;
4595 wire_addr
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
4596 mod
->children
.push_back(wire_addr
);
4597 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
4599 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
4600 wire_data
->str
= id_data
;
4601 wire_data
->is_reg
= true;
4602 wire_data
->was_checked
= true;
4603 wire_data
->is_signed
= mem_signed
;
4605 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
4606 mod
->children
.push_back(wire_data
);
4607 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
4609 AstNode
*assign_addr
= new AstNode(block
? AST_ASSIGN_EQ
: AST_ASSIGN
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->clone());
4610 assign_addr
->children
[0]->str
= id_addr
;
4611 assign_addr
->children
[0]->was_checked
= true;
4613 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
4614 case_node
->children
[0]->str
= id_addr
;
4616 for (int i
= 0; i
< mem_size
; i
++) {
4617 if (children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->integer
) != i
)
4619 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
4620 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
4621 assign_reg
->children
[0]->str
= id_data
;
4622 assign_reg
->children
[0]->was_checked
= true;
4623 assign_reg
->children
[1]->str
= stringf("%s[%d]", str
.c_str(), i
);
4624 cond_node
->children
[1]->children
.push_back(assign_reg
);
4625 case_node
->children
.push_back(cond_node
);
4628 std::vector
<RTLIL::State
> x_bits
;
4629 for (int i
= 0; i
< mem_width
; i
++)
4630 x_bits
.push_back(RTLIL::State::Sx
);
4632 AstNode
*cond_node
= new AstNode(AST_COND
, new AstNode(AST_DEFAULT
), new AstNode(AST_BLOCK
));
4633 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), AstNode::mkconst_bits(x_bits
, false));
4634 assign_reg
->children
[0]->str
= id_data
;
4635 assign_reg
->children
[0]->was_checked
= true;
4636 cond_node
->children
[1]->children
.push_back(assign_reg
);
4637 case_node
->children
.push_back(cond_node
);
4641 size_t assign_idx
= 0;
4642 while (assign_idx
< block
->children
.size() && !block
->children
[assign_idx
]->contains(this))
4644 log_assert(assign_idx
< block
->children
.size());
4645 block
->children
.insert(block
->children
.begin()+assign_idx
, case_node
);
4646 block
->children
.insert(block
->children
.begin()+assign_idx
, assign_addr
);
4650 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
4651 proc
->children
[0]->children
.push_back(case_node
);
4652 mod
->children
.push_back(proc
);
4653 mod
->children
.push_back(assign_addr
);
4657 range_valid
= false;
4663 children
.push_back(bit_part_sel
);
4665 did_something
= true;
4668 log_assert(id2ast
== NULL
|| mem2reg_set
.count(id2ast
) == 0);
4670 auto children_list
= children
;
4671 for (size_t i
= 0; i
< children_list
.size(); i
++)
4672 if (children_list
[i
]->mem2reg_as_needed_pass2(mem2reg_set
, mod
, block
, async_block
))
4673 did_something
= true;
4675 return did_something
;
4678 // calculate memory dimensions
4679 void AstNode::meminfo(int &mem_width
, int &mem_size
, int &addr_bits
)
4681 log_assert(type
== AST_MEMORY
);
4683 mem_width
= children
[0]->range_left
- children
[0]->range_right
+ 1;
4684 mem_size
= children
[1]->range_left
- children
[1]->range_right
;
4688 mem_size
+= min(children
[1]->range_left
, children
[1]->range_right
) + 1;
4691 while ((1 << addr_bits
) < mem_size
)
4695 bool AstNode::detect_latch(const std::string
&var
)
4700 for (auto &c
: children
)
4710 if (!c
->detect_latch(var
))
4719 for (auto &c
: children
)
4720 if (!c
->detect_latch(var
))
4726 for (auto &c
: children
) {
4727 if (c
->type
== AST_COND
) {
4728 if (c
->children
.at(1)->detect_latch(var
))
4732 if (c
->type
== AST_DEFAULT
) {
4733 if (c
->children
.at(0)->detect_latch(var
))
4742 if (children
.at(0)->type
== AST_IDENTIFIER
&&
4743 children
.at(0)->children
.empty() && children
.at(0)->str
== var
)
4751 bool AstNode::has_const_only_constructs()
4753 if (type
== AST_WHILE
|| type
== AST_REPEAT
)
4755 for (auto child
: children
)
4756 if (child
->has_const_only_constructs())
4761 bool AstNode::is_simple_const_expr()
4763 if (type
== AST_IDENTIFIER
)
4765 for (auto child
: children
)
4766 if (!child
->is_simple_const_expr())
4771 // helper function for AstNode::eval_const_function()
4772 bool AstNode::replace_variables(std::map
<std::string
, AstNode::varinfo_t
> &variables
, AstNode
*fcall
, bool must_succeed
)
4774 if (type
== AST_IDENTIFIER
&& variables
.count(str
)) {
4775 int offset
= variables
.at(str
).offset
, width
= variables
.at(str
).val
.bits
.size();
4776 if (!children
.empty()) {
4777 if (children
.size() != 1 || children
.at(0)->type
!= AST_RANGE
) {
4780 log_file_error(filename
, location
.first_line
, "Memory access in constant function is not supported\n%s: ...called from here.\n",
4781 fcall
->loc_string().c_str());
4783 if (!children
.at(0)->replace_variables(variables
, fcall
, must_succeed
))
4785 while (simplify(true, false, false, 1, -1, false, true)) { }
4786 if (!children
.at(0)->range_valid
) {
4789 log_file_error(filename
, location
.first_line
, "Non-constant range\n%s: ... called from here.\n",
4790 fcall
->loc_string().c_str());
4792 offset
= min(children
.at(0)->range_left
, children
.at(0)->range_right
);
4793 width
= min(std::abs(children
.at(0)->range_left
- children
.at(0)->range_right
) + 1, width
);
4795 offset
-= variables
.at(str
).offset
;
4796 std::vector
<RTLIL::State
> &var_bits
= variables
.at(str
).val
.bits
;
4797 std::vector
<RTLIL::State
> new_bits(var_bits
.begin() + offset
, var_bits
.begin() + offset
+ width
);
4798 AstNode
*newNode
= mkconst_bits(new_bits
, variables
.at(str
).is_signed
);
4799 newNode
->cloneInto(this);
4804 for (auto &child
: children
)
4805 if (!child
->replace_variables(variables
, fcall
, must_succeed
))
4810 // attempt to statically evaluate a functions with all-const arguments
4811 AstNode
*AstNode::eval_const_function(AstNode
*fcall
, bool must_succeed
)
4813 std::map
<std::string
, AstNode
*> backup_scope
= current_scope
;
4814 std::map
<std::string
, AstNode::varinfo_t
> variables
;
4815 std::vector
<AstNode
*> to_delete
;
4816 AstNode
*block
= new AstNode(AST_BLOCK
);
4817 AstNode
*result
= nullptr;
4820 for (auto child
: children
)
4822 block
->children
.push_back(child
->clone());
4825 while (!block
->children
.empty())
4827 AstNode
*stmt
= block
->children
.front();
4830 log("-----------------------------------\n");
4831 for (auto &it
: variables
)
4832 log("%20s %40s\n", it
.first
.c_str(), log_signal(it
.second
.val
));
4833 stmt
->dumpAst(NULL
, "stmt> ");
4836 if (stmt
->type
== AST_WIRE
)
4838 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
4839 if (!stmt
->range_valid
) {
4842 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Can't determine size of variable %s\n%s: ... called from here.\n",
4843 stmt
->str
.c_str(), fcall
->loc_string().c_str());
4845 AstNode::varinfo_t
&variable
= variables
[stmt
->str
];
4846 int width
= abs(stmt
->range_left
- stmt
->range_right
) + 1;
4847 // if this variable has already been declared as an input, check the
4848 // sizes match if it already had an explicit size
4849 if (variable
.arg
&& variable
.explicitly_sized
&& variable
.val
.size() != width
) {
4850 log_file_error(filename
, location
.first_line
, "Incompatible re-declaration of constant function wire %s.\n", stmt
->str
.c_str());
4852 variable
.val
= RTLIL::Const(RTLIL::State::Sx
, width
);
4853 variable
.offset
= min(stmt
->range_left
, stmt
->range_right
);
4854 variable
.is_signed
= stmt
->is_signed
;
4855 variable
.explicitly_sized
= stmt
->children
.size() &&
4856 stmt
->children
.back()->type
== AST_RANGE
;
4857 // identify the argument corresponding to this wire, if applicable
4858 if (stmt
->is_input
&& argidx
< fcall
->children
.size()) {
4859 variable
.arg
= fcall
->children
.at(argidx
++);
4861 // load the constant arg's value into this variable
4863 if (variable
.arg
->type
== AST_CONSTANT
) {
4864 variable
.val
= variable
.arg
->bitsAsConst(width
);
4866 log_assert(variable
.arg
->type
== AST_REALVALUE
);
4867 variable
.val
= variable
.arg
->realAsConst(width
);
4870 current_scope
[stmt
->str
] = stmt
;
4872 block
->children
.erase(block
->children
.begin());
4873 to_delete
.push_back(stmt
);
4877 log_assert(variables
.count(str
) != 0);
4879 if (stmt
->type
== AST_LOCALPARAM
)
4881 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
4883 current_scope
[stmt
->str
] = stmt
;
4885 block
->children
.erase(block
->children
.begin());
4886 to_delete
.push_back(stmt
);
4890 if (stmt
->type
== AST_ASSIGN_EQ
)
4892 if (stmt
->children
.at(0)->type
== AST_IDENTIFIER
&& stmt
->children
.at(0)->children
.size() != 0 &&
4893 stmt
->children
.at(0)->children
.at(0)->type
== AST_RANGE
)
4894 if (!stmt
->children
.at(0)->children
.at(0)->replace_variables(variables
, fcall
, must_succeed
))
4896 if (!stmt
->children
.at(1)->replace_variables(variables
, fcall
, must_succeed
))
4898 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
4900 if (stmt
->type
!= AST_ASSIGN_EQ
)
4903 if (stmt
->children
.at(1)->type
!= AST_CONSTANT
) {
4906 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s: ... called from here. X\n",
4907 fcall
->loc_string().c_str());
4910 if (stmt
->children
.at(0)->type
!= AST_IDENTIFIER
) {
4913 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Unsupported composite left hand side in constant function\n%s: ... called from here.\n",
4914 fcall
->loc_string().c_str());
4917 if (!variables
.count(stmt
->children
.at(0)->str
)) {
4920 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Assignment to non-local variable in constant function\n%s: ... called from here.\n",
4921 fcall
->loc_string().c_str());
4924 if (stmt
->children
.at(0)->children
.empty()) {
4925 variables
[stmt
->children
.at(0)->str
].val
= stmt
->children
.at(1)->bitsAsConst(variables
[stmt
->children
.at(0)->str
].val
.bits
.size());
4927 AstNode
*range
= stmt
->children
.at(0)->children
.at(0);
4928 if (!range
->range_valid
) {
4931 log_file_error(range
->filename
, range
->location
.first_line
, "Non-constant range\n%s: ... called from here.\n",
4932 fcall
->loc_string().c_str());
4934 int offset
= min(range
->range_left
, range
->range_right
);
4935 int width
= std::abs(range
->range_left
- range
->range_right
) + 1;
4936 varinfo_t
&v
= variables
[stmt
->children
.at(0)->str
];
4937 RTLIL::Const r
= stmt
->children
.at(1)->bitsAsConst(v
.val
.bits
.size());
4938 for (int i
= 0; i
< width
; i
++)
4939 v
.val
.bits
.at(i
+offset
-v
.offset
) = r
.bits
.at(i
);
4942 delete block
->children
.front();
4943 block
->children
.erase(block
->children
.begin());
4947 if (stmt
->type
== AST_FOR
)
4949 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(0));
4950 stmt
->children
.at(3)->children
.push_back(stmt
->children
.at(2));
4951 stmt
->children
.erase(stmt
->children
.begin() + 2);
4952 stmt
->children
.erase(stmt
->children
.begin());
4953 stmt
->type
= AST_WHILE
;
4957 if (stmt
->type
== AST_WHILE
)
4959 AstNode
*cond
= stmt
->children
.at(0)->clone();
4960 if (!cond
->replace_variables(variables
, fcall
, must_succeed
))
4962 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
4964 if (cond
->type
!= AST_CONSTANT
) {
4967 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s: ... called from here.\n",
4968 fcall
->loc_string().c_str());
4971 if (cond
->asBool()) {
4972 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
4974 delete block
->children
.front();
4975 block
->children
.erase(block
->children
.begin());
4982 if (stmt
->type
== AST_REPEAT
)
4984 AstNode
*num
= stmt
->children
.at(0)->clone();
4985 if (!num
->replace_variables(variables
, fcall
, must_succeed
))
4987 while (num
->simplify(true, false, false, 1, -1, false, true)) { }
4989 if (num
->type
!= AST_CONSTANT
) {
4992 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s: ... called from here.\n",
4993 fcall
->loc_string().c_str());
4996 block
->children
.erase(block
->children
.begin());
4997 for (int i
= 0; i
< num
->bitsAsConst().as_int(); i
++)
4998 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
5005 if (stmt
->type
== AST_CASE
)
5007 AstNode
*expr
= stmt
->children
.at(0)->clone();
5008 if (!expr
->replace_variables(variables
, fcall
, must_succeed
))
5010 while (expr
->simplify(true, false, false, 1, -1, false, true)) { }
5012 AstNode
*sel_case
= NULL
;
5013 for (size_t i
= 1; i
< stmt
->children
.size(); i
++)
5015 bool found_match
= false;
5016 log_assert(stmt
->children
.at(i
)->type
== AST_COND
|| stmt
->children
.at(i
)->type
== AST_CONDX
|| stmt
->children
.at(i
)->type
== AST_CONDZ
);
5018 if (stmt
->children
.at(i
)->children
.front()->type
== AST_DEFAULT
) {
5019 sel_case
= stmt
->children
.at(i
)->children
.back();
5023 for (size_t j
= 0; j
+1 < stmt
->children
.at(i
)->children
.size() && !found_match
; j
++)
5025 AstNode
*cond
= stmt
->children
.at(i
)->children
.at(j
)->clone();
5026 if (!cond
->replace_variables(variables
, fcall
, must_succeed
))
5029 cond
= new AstNode(AST_EQ
, expr
->clone(), cond
);
5030 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
5032 if (cond
->type
!= AST_CONSTANT
) {
5035 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s: ... called from here.\n",
5036 fcall
->loc_string().c_str());
5039 found_match
= cond
->asBool();
5044 sel_case
= stmt
->children
.at(i
)->children
.back();
5049 block
->children
.erase(block
->children
.begin());
5051 block
->children
.insert(block
->children
.begin(), sel_case
->clone());
5057 if (stmt
->type
== AST_BLOCK
)
5059 if (!stmt
->str
.empty())
5060 stmt
->expand_genblock(stmt
->str
+ ".");
5062 block
->children
.erase(block
->children
.begin());
5063 block
->children
.insert(block
->children
.begin(), stmt
->children
.begin(), stmt
->children
.end());
5064 stmt
->children
.clear();
5071 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Unsupported language construct in constant function\n%s: ... called from here.\n",
5072 fcall
->loc_string().c_str());
5076 result
= AstNode::mkconst_bits(variables
.at(str
).val
.bits
, variables
.at(str
).is_signed
);
5080 current_scope
= backup_scope
;
5082 for (auto it
: to_delete
) {
5090 void AstNode::allocateDefaultEnumValues()
5092 log_assert(type
==AST_ENUM
);
5093 log_assert(children
.size() > 0);
5094 if (children
.front()->attributes
.count(ID::enum_base_type
))
5095 return; // already elaborated
5096 int last_enum_int
= -1;
5097 for (auto node
: children
) {
5098 log_assert(node
->type
==AST_ENUM_ITEM
);
5099 node
->attributes
[ID::enum_base_type
] = mkconst_str(str
);
5100 for (size_t i
= 0; i
< node
->children
.size(); i
++) {
5101 switch (node
->children
[i
]->type
) {
5103 // replace with auto-incremented constant
5104 delete node
->children
[i
];
5105 node
->children
[i
] = AstNode::mkconst_int(++last_enum_int
, true);
5108 // explicit constant (or folded expression)
5109 // TODO: can't extend 'x or 'z item
5110 last_enum_int
= node
->children
[i
]->integer
;
5116 // TODO: range check
5121 bool AstNode::is_recursive_function() const
5123 std::set
<const AstNode
*> visited
;
5124 std::function
<bool(const AstNode
*node
)> visit
= [&](const AstNode
*node
) {
5125 if (visited
.count(node
))
5126 return node
== this;
5127 visited
.insert(node
);
5128 if (node
->type
== AST_FCALL
) {
5129 auto it
= current_scope
.find(node
->str
);
5130 if (it
!= current_scope
.end() && visit(it
->second
))
5133 for (const AstNode
*child
: node
->children
) {
5140 log_assert(type
== AST_FUNCTION
);
5144 std::pair
<AstNode
*, AstNode
*> AstNode::get_tern_choice()
5146 if (!children
[0]->isConst())
5149 bool found_sure_true
= false;
5150 bool found_maybe_true
= false;
5152 if (children
[0]->type
== AST_CONSTANT
)
5153 for (auto &bit
: children
[0]->bits
) {
5154 if (bit
== RTLIL::State::S1
)
5155 found_sure_true
= true;
5156 if (bit
> RTLIL::State::S1
)
5157 found_maybe_true
= true;
5160 found_sure_true
= children
[0]->asReal(true) != 0;
5162 AstNode
*choice
= nullptr, *not_choice
= nullptr;
5163 if (found_sure_true
)
5164 choice
= children
[1], not_choice
= children
[2];
5165 else if (!found_maybe_true
)
5166 choice
= children
[2], not_choice
= children
[1];
5168 return {choice
, not_choice
};
5171 std::string
AstNode::try_pop_module_prefix() const
5173 AstNode
*current_scope_ast
= (current_ast_mod
== nullptr) ? current_ast
: current_ast_mod
;
5174 size_t pos
= str
.find('.', 1);
5175 if (str
[0] == '\\' && pos
!= std::string::npos
) {
5176 std::string new_str
= "\\" + str
.substr(pos
+ 1);
5177 if (current_scope
.count(new_str
)) {
5178 std::string prefix
= str
.substr(0, pos
);
5179 auto it
= current_scope_ast
->attributes
.find(ID::hdlname
);
5180 if ((it
!= current_scope_ast
->attributes
.end() && it
->second
->str
== prefix
)
5181 || prefix
== current_scope_ast
->str
)