2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * This is the AST frontend library.
22 * The AST frontend library is not a frontend on it's own but provides a
23 * generic abstract syntax tree (AST) abstraction for HDL code and can be
24 * used by HDL frontends. See "ast.h" for an overview of the API and the
25 * Verilog frontend for an usage example.
29 #include "kernel/log.h"
30 #include "libs/sha1/sha1.h"
31 #include "frontends/verilog/verilog_frontend.h"
42 using namespace AST_INTERNAL
;
44 // Process a format string and arguments for $display, $write, $sprintf, etc
46 std::string
AstNode::process_format_str(const std::string
&sformat
, int next_arg
, int stage
, int width_hint
, bool sign_hint
) {
47 // Other arguments are placeholders. Process the string as we go through it
49 for (size_t i
= 0; i
< sformat
.length(); i
++)
52 if (sformat
[i
] == '%')
54 // If there's no next character, that's a problem
55 if (i
+1 >= sformat
.length())
56 log_file_error(filename
, location
.first_line
, "System task `%s' called with `%%' at end of string.\n", str
.c_str());
58 char cformat
= sformat
[++i
];
60 // %% is special, does not need a matching argument
68 bool got_zlen
= false;
71 while ('0' <= cformat
&& cformat
<= '9')
73 if (!got_len
&& cformat
== '0')
77 len_value
= 10*len_value
+ (cformat
- '0');
79 cformat
= sformat
[++i
];
82 // Simplify the argument
83 AstNode
*node_arg
= nullptr;
85 // Everything from here on depends on the format specifier
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 //get width from 1st enum item:
196 log_assert(enum_node
->children
.size() >= 1);
197 AstNode
*enum_item0
= enum_node
->children
[0];
198 log_assert(enum_item0
->type
== AST_ENUM_ITEM
);
200 if (!enum_item0
->range_valid
)
202 else if (enum_item0
->range_swapped
)
203 width
= enum_item0
->range_right
- enum_item0
->range_left
+ 1;
205 width
= enum_item0
->range_left
- enum_item0
->range_right
+ 1;
206 log_assert(width
> 0);
207 //add declared enum items:
208 for (auto enum_item
: enum_node
->children
){
209 log_assert(enum_item
->type
== AST_ENUM_ITEM
);
212 if (enum_item
->children
.size() == 1){
214 } else if (enum_item
->children
.size() == 2){
215 log_assert(enum_item
->children
[1]->type
== AST_RANGE
);
216 is_signed
= enum_item
->children
[1]->is_signed
;
218 log_error("enum_item children size==%lu, expected 1 or 2 for %s (%s)\n",
219 enum_item
->children
.size(),
220 enum_item
->str
.c_str(), enum_node
->str
.c_str()
223 //start building attribute string
224 std::string enum_item_str
= "\\enum_value_";
225 //get enum item value
226 if(enum_item
->children
[0]->type
!= AST_CONSTANT
){
227 log_error("expected const, got %s for %s (%s)\n",
228 type2str(enum_item
->children
[0]->type
).c_str(),
229 enum_item
->str
.c_str(), enum_node
->str
.c_str()
232 RTLIL::Const val
= enum_item
->children
[0]->bitsAsConst(width
, is_signed
);
233 enum_item_str
.append(val
.as_string());
234 //set attribute for available val to enum item name mappings
235 attributes
[enum_item_str
.c_str()] = mkconst_str(enum_item
->str
);
240 static bool name_has_dot(const std::string
&name
, std::string
&struct_name
)
242 // check if plausible struct member name \sss.mmm
243 std::string::size_type pos
;
244 if (name
.substr(0, 1) == "\\" && (pos
= name
.find('.', 0)) != std::string::npos
) {
245 struct_name
= name
.substr(0, pos
);
251 static AstNode
*make_range(int left
, int right
, bool is_signed
= false)
253 // generate a pre-validated range node for a fixed signal range.
254 auto range
= new AstNode(AST_RANGE
);
255 range
->range_left
= left
;
256 range
->range_right
= right
;
257 range
->range_valid
= true;
258 range
->children
.push_back(AstNode::mkconst_int(left
, true));
259 range
->children
.push_back(AstNode::mkconst_int(right
, true));
260 range
->is_signed
= is_signed
;
264 static int range_width(AstNode
*node
, AstNode
*rnode
)
266 log_assert(rnode
->type
==AST_RANGE
);
267 if (!rnode
->range_valid
) {
268 log_file_error(node
->filename
, node
->location
.first_line
, "Size must be constant in packed struct/union member %s\n", node
->str
.c_str());
271 // note: range swapping has already been checked for
272 return rnode
->range_left
- rnode
->range_right
+ 1;
275 [[noreturn
]] static void struct_array_packing_error(AstNode
*node
)
277 log_file_error(node
->filename
, node
->location
.first_line
, "Unpacked array in packed struct/union member %s\n", node
->str
.c_str());
280 static void save_struct_array_width(AstNode
*node
, int width
)
282 // stash the stride for the array
283 node
->multirange_dimensions
.push_back(width
);
287 static int get_struct_array_width(AstNode
*node
)
289 // the stride for the array, 1 if not an array
290 return (node
->multirange_dimensions
.empty() ? 1 : node
->multirange_dimensions
.back());
294 static int size_packed_struct(AstNode
*snode
, int base_offset
)
296 // Struct members will be laid out in the structure contiguously from left to right.
297 // Union members all have zero offset from the start of the union.
298 // Determine total packed size and assign offsets. Store these in the member node.
299 bool is_union
= (snode
->type
== AST_UNION
);
301 int packed_width
= -1;
302 // examine members from last to first
303 for (auto it
= snode
->children
.rbegin(); it
!= snode
->children
.rend(); ++it
) {
306 if (node
->type
== AST_STRUCT
|| node
->type
== AST_UNION
) {
307 // embedded struct or union
308 width
= size_packed_struct(node
, base_offset
+ offset
);
311 log_assert(node
->type
== AST_STRUCT_ITEM
);
312 if (node
->children
.size() > 0 && node
->children
[0]->type
== AST_RANGE
) {
313 // member width e.g. bit [7:0] a
314 width
= range_width(node
, node
->children
[0]);
315 if (node
->children
.size() == 2) {
316 if (node
->children
[1]->type
== AST_RANGE
) {
317 // unpacked array e.g. bit [63:0] a [0:3]
318 auto rnode
= node
->children
[1];
319 int array_count
= range_width(node
, rnode
);
320 if (array_count
== 1) {
321 // C-type array size e.g. bit [63:0] a [4]
322 array_count
= rnode
->range_left
;
324 save_struct_array_width(node
, width
);
325 width
*= array_count
;
328 // array element must be single bit for a packed array
329 struct_array_packing_error(node
);
332 // range nodes are now redundant
333 node
->children
.clear();
335 else if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_MULTIRANGE
) {
336 // packed 2D array, e.g. bit [3:0][63:0] a
337 auto rnode
= node
->children
[0];
338 if (rnode
->children
.size() != 2) {
339 // packed arrays can only be 2D
340 struct_array_packing_error(node
);
342 int array_count
= range_width(node
, rnode
->children
[0]);
343 width
= range_width(node
, rnode
->children
[1]);
344 save_struct_array_width(node
, width
);
345 width
*= array_count
;
346 // range nodes are now redundant
347 node
->children
.clear();
349 else if (node
->range_left
< 0) {
350 // 1 bit signal: bit, logic or reg
354 // already resolved and compacted
355 width
= node
->range_left
- node
->range_right
+ 1;
358 node
->range_right
= base_offset
;
359 node
->range_left
= base_offset
+ width
- 1;
362 node
->range_right
= base_offset
+ offset
;
363 node
->range_left
= base_offset
+ offset
+ width
- 1;
365 node
->range_valid
= true;
368 // check that all members have the same size
369 if (packed_width
== -1) {
371 packed_width
= width
;
374 if (packed_width
!= width
) {
376 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
);
384 return (is_union
? packed_width
: offset
);
387 [[noreturn
]] static void struct_op_error(AstNode
*node
)
389 log_file_error(node
->filename
, node
->location
.first_line
, "Unsupported operation for struct/union member %s\n", node
->str
.c_str()+1);
392 static AstNode
*node_int(int ival
)
394 return AstNode::mkconst_int(ival
, true);
397 static AstNode
*multiply_by_const(AstNode
*expr_node
, int stride
)
399 return new AstNode(AST_MUL
, expr_node
, node_int(stride
));
402 static AstNode
*offset_indexed_range(int offset
, int stride
, AstNode
*left_expr
, AstNode
*right_expr
)
404 // adjust the range expressions to add an offset into the struct
405 // and maybe index using an array stride
406 auto left
= left_expr
->clone();
407 auto right
= right_expr
->clone();
409 // newleft = (left + 1) * stride - 1
410 left
= new AstNode(AST_SUB
, multiply_by_const(new AstNode(AST_ADD
, left
, node_int(1)), stride
), node_int(1));
411 // newright = right * stride
412 right
= multiply_by_const(right
, stride
);
416 left
= new AstNode(AST_ADD
, node_int(offset
), left
);
417 right
= new AstNode(AST_ADD
, node_int(offset
), right
);
419 return new AstNode(AST_RANGE
, left
, right
);
422 static AstNode
*make_struct_index_range(AstNode
*node
, AstNode
*rnode
, int stride
, int offset
)
424 // generate a range node to perform either bit or array indexing
425 if (rnode
->children
.size() == 1) {
427 return offset_indexed_range(offset
, stride
, rnode
->children
[0], rnode
->children
[0]);
429 else if (rnode
->children
.size() == 2) {
430 // slice e.g. s.a[i:j]
431 return offset_indexed_range(offset
, stride
, rnode
->children
[0], rnode
->children
[1]);
434 struct_op_error(node
);
438 static AstNode
*slice_range(AstNode
*rnode
, AstNode
*snode
)
440 // apply the bit slice indicated by snode to the range rnode
441 log_assert(rnode
->type
==AST_RANGE
);
442 auto left
= rnode
->children
[0];
443 auto right
= rnode
->children
[1];
444 log_assert(snode
->type
==AST_RANGE
);
445 auto slice_left
= snode
->children
[0];
446 auto slice_right
= snode
->children
[1];
447 auto width
= new AstNode(AST_SUB
, slice_left
->clone(), slice_right
->clone());
448 right
= new AstNode(AST_ADD
, right
->clone(), slice_right
->clone());
449 left
= new AstNode(AST_ADD
, right
->clone(), width
);
450 return new AstNode(AST_RANGE
, left
, right
);
454 static AstNode
*make_struct_member_range(AstNode
*node
, AstNode
*member_node
)
456 // Work out the range in the packed array that corresponds to a struct member
457 // taking into account any range operations applicable to the current node
458 // such as array indexing or slicing
459 int range_left
= member_node
->range_left
;
460 int range_right
= member_node
->range_right
;
461 if (node
->children
.empty()) {
462 // no range operations apply, return the whole width
463 return make_range(range_left
, range_right
);
465 int stride
= get_struct_array_width(member_node
);
466 if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
467 // bit or array indexing e.g. s.a[2] or s.a[1:0]
468 return make_struct_index_range(node
, node
->children
[0], stride
, range_right
);
470 else if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_MULTIRANGE
) {
471 // multirange, i.e. bit slice after array index, e.g. s.a[i][p:q]
472 log_assert(stride
> 1);
473 auto mrnode
= node
->children
[0];
474 auto element_range
= make_struct_index_range(node
, mrnode
->children
[0], stride
, range_right
);
475 // then apply bit slice range
476 auto range
= slice_range(element_range
, mrnode
->children
[1]);
477 delete element_range
;
481 struct_op_error(node
);
485 static void add_members_to_scope(AstNode
*snode
, std::string name
)
487 // add all the members in a struct or union to local scope
488 // in case later referenced in assignments
489 log_assert(snode
->type
==AST_STRUCT
|| snode
->type
==AST_UNION
);
490 for (auto *node
: snode
->children
) {
491 if (node
->type
!= AST_STRUCT_ITEM
) {
492 // embedded struct or union
493 add_members_to_scope(node
, name
+ "." + node
->str
);
496 auto member_name
= name
+ "." + node
->str
;
497 current_scope
[member_name
] = node
;
502 static int get_max_offset(AstNode
*node
)
504 // get the width from the MS member in the struct
505 // as members are laid out from left to right in the packed wire
506 log_assert(node
->type
==AST_STRUCT
|| node
->type
==AST_UNION
);
507 while (node
->type
!= AST_STRUCT_ITEM
) {
508 node
= node
->children
[0];
510 return node
->range_left
;
513 static AstNode
*make_packed_struct(AstNode
*template_node
, std::string
&name
)
515 // create a wire for the packed struct
516 auto wnode
= new AstNode(AST_WIRE
);
518 wnode
->is_logic
= true;
519 wnode
->range_valid
= true;
520 wnode
->is_signed
= template_node
->is_signed
;
521 int offset
= get_max_offset(template_node
);
522 auto range
= make_range(offset
, 0);
523 wnode
->children
.push_back(range
);
524 // make sure this node is the one in scope for this name
525 current_scope
[name
] = wnode
;
526 // add all the struct members to scope under the wire's name
527 add_members_to_scope(template_node
, name
);
531 // check if a node or its children contains an assignment to the given variable
532 static bool node_contains_assignment_to(const AstNode
* node
, const AstNode
* var
)
534 if (node
->type
== AST_ASSIGN_EQ
|| node
->type
== AST_ASSIGN_LE
) {
535 // current node is iteslf an assignment
536 log_assert(node
->children
.size() >= 2);
537 const AstNode
* lhs
= node
->children
[0];
538 if (lhs
->type
== AST_IDENTIFIER
&& lhs
->str
== var
->str
)
541 for (const AstNode
* child
: node
->children
) {
542 // if this child shadows the given variable
543 if (child
!= var
&& child
->str
== var
->str
&& child
->type
== AST_WIRE
)
544 break; // skip the remainder of this block/scope
545 // depth-first short circuit
546 if (!node_contains_assignment_to(child
, var
))
552 // convert the AST into a simpler AST that has all parameters substituted by their
553 // values, unrolled for-loops, expanded generate blocks, etc. when this function
554 // is done with an AST it can be converted into RTLIL using genRTLIL().
556 // this function also does all name resolving and sets the id2ast member of all
557 // nodes that link to a different node using names and lexical scoping.
558 bool AstNode::simplify(bool const_fold
, bool at_zero
, bool in_lvalue
, int stage
, int width_hint
, bool sign_hint
, bool in_param
)
560 static int recursion_counter
= 0;
561 static bool deep_recursion_warning
= false;
563 if (recursion_counter
++ == 1000 && deep_recursion_warning
) {
564 log_warning("Deep recursion in AST simplifier.\nDoes this design contain insanely long expressions?\n");
565 deep_recursion_warning
= false;
568 AstNode
*newNode
= NULL
;
569 bool did_something
= false;
572 log("-------------\n");
573 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);
574 log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
575 int(const_fold
), int(at_zero
), int(in_lvalue
), int(stage
), int(width_hint
), int(sign_hint
), int(in_param
));
576 // dumpAst(NULL, "> ");
581 log_assert(type
== AST_MODULE
|| type
== AST_INTERFACE
);
583 deep_recursion_warning
= true;
584 while (simplify(const_fold
, at_zero
, in_lvalue
, 1, width_hint
, sign_hint
, in_param
)) { }
586 if (!flag_nomem2reg
&& !get_bool_attribute(ID::nomem2reg
))
588 dict
<AstNode
*, pool
<std::string
>> mem2reg_places
;
589 dict
<AstNode
*, uint32_t> mem2reg_candidates
, dummy_proc_flags
;
590 uint32_t flags
= flag_mem2reg
? AstNode::MEM2REG_FL_ALL
: 0;
591 mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, dummy_proc_flags
, flags
);
593 pool
<AstNode
*> mem2reg_set
;
594 for (auto &it
: mem2reg_candidates
)
596 AstNode
*mem
= it
.first
;
597 uint32_t memflags
= it
.second
;
598 bool this_nomeminit
= flag_nomeminit
;
599 log_assert((memflags
& ~0x00ffff00) == 0);
601 if (mem
->get_bool_attribute(ID::nomem2reg
))
604 if (mem
->get_bool_attribute(ID::nomeminit
) || get_bool_attribute(ID::nomeminit
))
605 this_nomeminit
= true;
607 if (memflags
& AstNode::MEM2REG_FL_FORCED
)
608 goto silent_activate
;
610 if (memflags
& AstNode::MEM2REG_FL_EQ2
)
611 goto verbose_activate
;
613 if (memflags
& AstNode::MEM2REG_FL_SET_ASYNC
)
614 goto verbose_activate
;
616 if ((memflags
& AstNode::MEM2REG_FL_SET_INIT
) && (memflags
& AstNode::MEM2REG_FL_SET_ELSE
) && this_nomeminit
)
617 goto verbose_activate
;
619 if (memflags
& AstNode::MEM2REG_FL_CMPLX_LHS
)
620 goto verbose_activate
;
622 if ((memflags
& AstNode::MEM2REG_FL_CONST_LHS
) && !(memflags
& AstNode::MEM2REG_FL_VAR_LHS
))
623 goto verbose_activate
;
625 // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
629 if (mem2reg_set
.count(mem
) == 0) {
630 std::string message
= stringf("Replacing memory %s with list of registers.", mem
->str
.c_str());
631 bool first_element
= true;
632 for (auto &place
: mem2reg_places
[it
.first
]) {
633 message
+= stringf("%s%s", first_element
? " See " : ", ", place
.c_str());
634 first_element
= false;
636 log_warning("%s\n", message
.c_str());
640 // log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
641 mem2reg_set
.insert(mem
);
644 for (auto node
: mem2reg_set
)
646 int mem_width
, mem_size
, addr_bits
;
647 node
->meminfo(mem_width
, mem_size
, addr_bits
);
649 int data_range_left
= node
->children
[0]->range_left
;
650 int data_range_right
= node
->children
[0]->range_right
;
652 if (node
->children
[0]->range_swapped
)
653 std::swap(data_range_left
, data_range_right
);
655 for (int i
= 0; i
< mem_size
; i
++) {
656 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
657 mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
658 reg
->str
= stringf("%s[%d]", node
->str
.c_str(), i
);
660 reg
->is_signed
= node
->is_signed
;
661 for (auto &it
: node
->attributes
)
662 if (it
.first
!= ID::mem2reg
)
663 reg
->attributes
.emplace(it
.first
, it
.second
->clone());
664 reg
->filename
= node
->filename
;
665 reg
->location
= node
->location
;
666 children
.push_back(reg
);
667 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
671 AstNode
*async_block
= NULL
;
672 while (mem2reg_as_needed_pass2(mem2reg_set
, this, NULL
, async_block
)) { }
674 vector
<AstNode
*> delnodes
;
675 mem2reg_remove(mem2reg_set
, delnodes
);
677 for (auto node
: delnodes
)
681 while (simplify(const_fold
, at_zero
, in_lvalue
, 2, width_hint
, sign_hint
, in_param
)) { }
686 current_filename
= filename
;
688 // we do not look inside a task or function
689 // (but as soon as a task or function is instantiated we process the generated AST as usual)
690 if (type
== AST_FUNCTION
|| type
== AST_TASK
) {
695 // deactivate all calls to non-synthesis system tasks
696 // note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
697 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && (str
== "$strobe" || str
== "$monitor" || str
== "$time" ||
698 str
== "$dumpfile" || str
== "$dumpvars" || str
== "$dumpon" || str
== "$dumpoff" || str
== "$dumpall")) {
699 log_file_warning(filename
, location
.first_line
, "Ignoring call to system %s %s.\n", type
== AST_FCALL
? "function" : "task", str
.c_str());
704 if ((type
== AST_TCALL
) && (str
== "$display" || str
== "$write") && (!current_always
|| current_always
->type
!= AST_INITIAL
)) {
705 log_file_warning(filename
, location
.first_line
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
710 // print messages if this a call to $display() or $write()
711 // This code implements only a small subset of Verilog-2005 $display() format specifiers,
712 // but should be good enough for most uses
713 if ((type
== AST_TCALL
) && ((str
== "$display") || (str
== "$write")))
715 int nargs
= GetSize(children
);
717 log_file_error(filename
, location
.first_line
, "System task `%s' got %d arguments, expected >= 1.\n",
718 str
.c_str(), int(children
.size()));
720 // First argument is the format string
721 AstNode
*node_string
= children
[0];
722 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
723 if (node_string
->type
!= AST_CONSTANT
)
724 log_file_error(filename
, location
.first_line
, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str
.c_str());
725 std::string sformat
= node_string
->bitsAsConst().decode_string();
726 std::string sout
= process_format_str(sformat
, 1, stage
, width_hint
, sign_hint
);
727 // Finally, print the message (only include a \n for $display, not for $write)
728 log("%s", sout
.c_str());
729 if (str
== "$display")
735 // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
736 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
)
738 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
))
741 // in certain cases a function must be evaluated constant. this is what in_param controls.
742 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_PREFIX
)
745 std::map
<std::string
, AstNode
*> backup_scope
;
747 // create name resolution entries for all objects with names
748 // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
749 if (type
== AST_MODULE
) {
750 current_scope
.clear();
751 std::map
<std::string
, AstNode
*> this_wire_scope
;
752 for (size_t i
= 0; i
< children
.size(); i
++) {
753 AstNode
*node
= children
[i
];
755 if (node
->type
== AST_WIRE
) {
756 if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
757 for (auto c
: node
->children
[0]->children
) {
758 if (!c
->is_simple_const_expr()) {
759 if (attributes
.count(ID::dynports
))
760 delete attributes
.at(ID::dynports
);
761 attributes
[ID::dynports
] = AstNode::mkconst_int(1, true);
765 if (this_wire_scope
.count(node
->str
) > 0) {
766 AstNode
*first_node
= this_wire_scope
[node
->str
];
767 if (first_node
->is_input
&& node
->is_reg
)
768 goto wires_are_incompatible
;
769 if (!node
->is_input
&& !node
->is_output
&& node
->is_reg
&& node
->children
.size() == 0)
770 goto wires_are_compatible
;
771 if (first_node
->children
.size() == 0 && node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
772 AstNode
*r
= node
->children
[0];
773 if (r
->range_valid
&& r
->range_left
== 0 && r
->range_right
== 0) {
775 node
->children
.pop_back();
778 if (first_node
->children
.size() != node
->children
.size())
779 goto wires_are_incompatible
;
780 for (size_t j
= 0; j
< node
->children
.size(); j
++) {
781 AstNode
*n1
= first_node
->children
[j
], *n2
= node
->children
[j
];
782 if (n1
->type
== AST_RANGE
&& n2
->type
== AST_RANGE
&& n1
->range_valid
&& n2
->range_valid
) {
783 if (n1
->range_left
!= n2
->range_left
)
784 goto wires_are_incompatible
;
785 if (n1
->range_right
!= n2
->range_right
)
786 goto wires_are_incompatible
;
787 } else if (*n1
!= *n2
)
788 goto wires_are_incompatible
;
790 if (first_node
->range_left
!= node
->range_left
)
791 goto wires_are_incompatible
;
792 if (first_node
->range_right
!= node
->range_right
)
793 goto wires_are_incompatible
;
794 if (first_node
->port_id
== 0 && (node
->is_input
|| node
->is_output
))
795 goto wires_are_incompatible
;
796 wires_are_compatible
:
798 first_node
->is_input
= true;
800 first_node
->is_output
= true;
802 first_node
->is_reg
= true;
804 first_node
->is_logic
= true;
806 first_node
->is_signed
= true;
807 for (auto &it
: node
->attributes
) {
808 if (first_node
->attributes
.count(it
.first
) > 0)
809 delete first_node
->attributes
[it
.first
];
810 first_node
->attributes
[it
.first
] = it
.second
->clone();
812 children
.erase(children
.begin()+(i
--));
813 did_something
= true;
816 wires_are_incompatible
:
818 log_file_error(filename
, location
.first_line
, "Incompatible re-declaration of wire %s.\n", node
->str
.c_str());
821 this_wire_scope
[node
->str
] = node
;
823 // these nodes appear at the top level in a module and can define names
824 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
825 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
|| node
->type
== AST_CELL
||
826 node
->type
== AST_TYPEDEF
) {
827 backup_scope
[node
->str
] = current_scope
[node
->str
];
828 current_scope
[node
->str
] = node
;
830 if (node
->type
== AST_ENUM
) {
831 current_scope
[node
->str
] = node
;
832 for (auto enode
: node
->children
) {
833 log_assert(enode
->type
==AST_ENUM_ITEM
);
834 if (current_scope
.count(enode
->str
) == 0)
835 current_scope
[enode
->str
] = enode
;
837 log_file_error(filename
, location
.first_line
, "enum item %s already exists\n", enode
->str
.c_str());
841 for (size_t i
= 0; i
< children
.size(); i
++) {
842 AstNode
*node
= children
[i
];
843 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
)
844 while (node
->simplify(true, false, false, 1, -1, false, node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
))
845 did_something
= true;
846 if (node
->type
== AST_ENUM
) {
847 for (auto enode
: node
->children
){
848 log_assert(enode
->type
==AST_ENUM_ITEM
);
849 while (node
->simplify(true, false, false, 1, -1, false, in_param
))
850 did_something
= true;
856 // create name resolution entries for all objects with names
857 if (type
== AST_PACKAGE
) {
858 //add names to package scope
859 for (size_t i
= 0; i
< children
.size(); i
++) {
860 AstNode
*node
= children
[i
];
861 // these nodes appear at the top level in a package and can define names
862 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_TYPEDEF
) {
863 current_scope
[node
->str
] = node
;
865 if (node
->type
== AST_ENUM
) {
866 current_scope
[node
->str
] = node
;
867 for (auto enode
: node
->children
) {
868 log_assert(enode
->type
==AST_ENUM_ITEM
);
869 if (current_scope
.count(enode
->str
) == 0)
870 current_scope
[enode
->str
] = enode
;
872 log_file_error(filename
, location
.first_line
, "enum item %s already exists in package\n", enode
->str
.c_str());
879 auto backup_current_block
= current_block
;
880 auto backup_current_block_child
= current_block_child
;
881 auto backup_current_top_block
= current_top_block
;
882 auto backup_current_always
= current_always
;
883 auto backup_current_always_clocked
= current_always_clocked
;
885 if (type
== AST_ALWAYS
|| type
== AST_INITIAL
)
887 if (current_always
!= nullptr)
888 log_file_error(filename
, location
.first_line
, "Invalid nesting of always blocks and/or initializations.\n");
890 current_always
= this;
891 current_always_clocked
= false;
893 if (type
== AST_ALWAYS
)
894 for (auto child
: children
) {
895 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
896 current_always_clocked
= true;
897 if (child
->type
== AST_EDGE
&& GetSize(child
->children
) == 1 &&
898 child
->children
[0]->type
== AST_IDENTIFIER
&& child
->children
[0]->str
== "\\$global_clock")
899 current_always_clocked
= true;
903 int backup_width_hint
= width_hint
;
904 bool backup_sign_hint
= sign_hint
;
906 bool detect_width_simple
= false;
907 bool child_0_is_self_determined
= false;
908 bool child_1_is_self_determined
= false;
909 bool child_2_is_self_determined
= false;
910 bool children_are_self_determined
= false;
911 bool reset_width_after_children
= false;
918 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, true, stage
, -1, false, in_param
) == true)
919 did_something
= true;
920 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
) == true)
921 did_something
= true;
922 children
[0]->detectSignWidth(backup_width_hint
, backup_sign_hint
);
923 children
[1]->detectSignWidth(width_hint
, sign_hint
);
924 width_hint
= max(width_hint
, backup_width_hint
);
925 child_0_is_self_determined
= true;
926 // test only once, before optimizations and memory mappings but after assignment LHS was mapped to an identifier
927 if (children
[0]->id2ast
&& !children
[0]->was_checked
) {
928 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->id2ast
->is_logic
)
929 children
[0]->id2ast
->is_reg
= true; // if logic type is used in a block asignment
930 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && !children
[0]->id2ast
->is_reg
)
931 log_warning("wire '%s' is assigned in a block at %s:%d.%d-%d.%d.\n", children
[0]->str
.c_str(), filename
.c_str(), location
.first_line
, location
.first_column
, location
.last_line
, location
.last_column
);
932 if (type
== AST_ASSIGN
&& children
[0]->id2ast
->is_reg
) {
933 bool is_rand_reg
= false;
934 if (children
[1]->type
== AST_FCALL
) {
935 if (children
[1]->str
== "\\$anyconst")
937 if (children
[1]->str
== "\\$anyseq")
939 if (children
[1]->str
== "\\$allconst")
941 if (children
[1]->str
== "\\$allseq")
945 log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.%d-%d.%d.\n", children
[0]->str
.c_str(), filename
.c_str(), location
.first_line
, location
.first_column
, location
.last_line
, location
.last_column
);
947 children
[0]->was_checked
= true;
954 for (auto *node
: children
) {
955 // resolve any ranges
956 while (!node
->basic_prep
&& node
->simplify(true, false, false, stage
, -1, false, false)) {
957 did_something
= true;
960 // determine member offsets and widths
961 size_packed_struct(this, 0);
963 // instance rather than just a type in a typedef or outer struct?
964 if (!str
.empty() && str
[0] == '\\') {
965 // instance so add a wire for the packed structure
966 auto wnode
= make_packed_struct(this, str
);
967 log_assert(current_ast_mod
);
968 current_ast_mod
->children
.push_back(wnode
);
974 case AST_STRUCT_ITEM
:
978 //log("\nENUM %s: %d child %d\n", str.c_str(), basic_prep, children[0]->basic_prep);
980 for (auto item_node
: children
) {
981 while (!item_node
->basic_prep
&& item_node
->simplify(false, false, false, stage
, -1, false, in_param
))
982 did_something
= true;
984 // allocate values (called more than once)
985 allocateDefaultEnumValues();
991 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, true) == true)
992 did_something
= true;
993 children
[0]->detectSignWidth(width_hint
, sign_hint
);
994 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
995 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, true) == true)
996 did_something
= true;
997 if (!children
[1]->range_valid
)
998 log_file_error(filename
, location
.first_line
, "Non-constant width range on parameter decl.\n");
999 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
1003 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, in_param
))
1004 did_something
= true;
1005 children
[0]->detectSignWidth(width_hint
, sign_hint
);
1006 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
1007 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
))
1008 did_something
= true;
1009 if (!children
[1]->range_valid
)
1010 log_file_error(filename
, location
.first_line
, "Non-constant width range on enum item decl.\n");
1011 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
1017 case AST_TO_UNSIGNED
:
1022 case AST_REDUCE_AND
:
1024 case AST_REDUCE_XOR
:
1025 case AST_REDUCE_XNOR
:
1026 case AST_REDUCE_BOOL
:
1027 detect_width_simple
= true;
1028 children_are_self_determined
= true;
1043 detect_width_simple
= true;
1046 case AST_SHIFT_LEFT
:
1047 case AST_SHIFT_RIGHT
:
1048 case AST_SHIFT_SLEFT
:
1049 case AST_SHIFT_SRIGHT
:
1051 detect_width_simple
= true;
1052 child_1_is_self_determined
= true;
1065 for (auto child
: children
) {
1066 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
1067 did_something
= true;
1068 child
->detectSignWidthWorker(width_hint
, sign_hint
);
1070 reset_width_after_children
= true;
1076 detect_width_simple
= true;
1077 children_are_self_determined
= true;
1081 detect_width_simple
= true;
1082 child_0_is_self_determined
= true;
1086 detect_width_simple
= true;
1087 children_are_self_determined
= true;
1092 children_are_self_determined
= true;
1100 if (detect_width_simple
&& width_hint
< 0) {
1101 if (type
== AST_REPLICATE
)
1102 while (children
[0]->simplify(true, false, in_lvalue
, stage
, -1, false, true) == true)
1103 did_something
= true;
1104 for (auto child
: children
)
1105 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
1106 did_something
= true;
1107 detectSignWidth(width_hint
, sign_hint
);
1110 if (type
== AST_FCALL
&& str
== "\\$past")
1111 detectSignWidth(width_hint
, sign_hint
);
1113 if (type
== AST_TERNARY
) {
1114 int width_hint_left
, width_hint_right
;
1115 bool sign_hint_left
, sign_hint_right
;
1116 bool found_real_left
, found_real_right
;
1117 children
[1]->detectSignWidth(width_hint_left
, sign_hint_left
, &found_real_left
);
1118 children
[2]->detectSignWidth(width_hint_right
, sign_hint_right
, &found_real_right
);
1119 if (found_real_left
|| found_real_right
) {
1120 child_1_is_self_determined
= true;
1121 child_2_is_self_determined
= true;
1125 if (type
== AST_CONDX
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
1126 for (auto &bit
: children
.at(0)->bits
)
1127 if (bit
== State::Sz
|| bit
== State::Sx
)
1131 if (type
== AST_CONDZ
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
1132 for (auto &bit
: children
.at(0)->bits
)
1133 if (bit
== State::Sz
)
1137 if (const_fold
&& type
== AST_CASE
)
1139 while (children
[0]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
1140 if (children
[0]->type
== AST_CONSTANT
&& children
[0]->bits_only_01()) {
1141 std::vector
<AstNode
*> new_children
;
1142 new_children
.push_back(children
[0]);
1143 for (int i
= 1; i
< GetSize(children
); i
++) {
1144 AstNode
*child
= children
[i
];
1145 log_assert(child
->type
== AST_COND
|| child
->type
== AST_CONDX
|| child
->type
== AST_CONDZ
);
1146 for (auto v
: child
->children
) {
1147 if (v
->type
== AST_DEFAULT
)
1148 goto keep_const_cond
;
1149 if (v
->type
== AST_BLOCK
)
1151 while (v
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
1152 if (v
->type
== AST_CONSTANT
&& v
->bits_only_01()) {
1153 if (v
->bits
== children
[0]->bits
) {
1154 while (i
+1 < GetSize(children
))
1155 delete children
[++i
];
1156 goto keep_const_cond
;
1160 goto keep_const_cond
;
1164 new_children
.push_back(child
);
1168 new_children
.swap(children
);
1172 // simplify all children first
1173 // (iterate by index as e.g. auto wires can add new children in the process)
1174 for (size_t i
= 0; i
< children
.size(); i
++) {
1175 bool did_something_here
= true;
1176 bool backup_flag_autowire
= flag_autowire
;
1177 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && i
>= 3)
1179 if ((type
== AST_GENIF
|| type
== AST_GENCASE
) && i
>= 1)
1181 if (type
== AST_GENBLOCK
)
1183 if (type
== AST_BLOCK
&& !str
.empty())
1185 if (type
== AST_PREFIX
&& i
>= 1)
1187 if (type
== AST_DEFPARAM
&& i
== 0)
1188 flag_autowire
= true;
1189 while (did_something_here
&& i
< children
.size()) {
1190 bool const_fold_here
= const_fold
, in_lvalue_here
= in_lvalue
;
1191 int width_hint_here
= width_hint
;
1192 bool sign_hint_here
= sign_hint
;
1193 bool in_param_here
= in_param
;
1194 if (i
== 0 && (type
== AST_REPLICATE
|| type
== AST_WIRE
))
1195 const_fold_here
= true, in_param_here
= true;
1196 if (i
== 0 && (type
== AST_GENIF
|| type
== AST_GENCASE
))
1197 in_param_here
= true;
1198 if (i
== 1 && (type
== AST_FOR
|| type
== AST_GENFOR
))
1199 in_param_here
= true;
1200 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
)
1201 const_fold_here
= true;
1202 if (i
== 0 && (type
== AST_ASSIGN
|| type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
))
1203 in_lvalue_here
= true;
1204 if (type
== AST_BLOCK
) {
1205 current_block
= this;
1206 current_block_child
= children
[i
];
1208 if (!in_param_here
&& type
== AST_FCALL
) {
1209 bool recommend_const_eval
= false;
1210 bool require_const_eval
= has_const_only_constructs(recommend_const_eval
);
1211 in_param_here
= recommend_const_eval
|| require_const_eval
;
1213 if ((type
== AST_ALWAYS
|| type
== AST_INITIAL
) && children
[i
]->type
== AST_BLOCK
)
1214 current_top_block
= children
[i
];
1215 if (i
== 0 && child_0_is_self_determined
)
1216 width_hint_here
= -1, sign_hint_here
= false;
1217 if (i
== 1 && child_1_is_self_determined
)
1218 width_hint_here
= -1, sign_hint_here
= false;
1219 if (i
== 2 && child_2_is_self_determined
)
1220 width_hint_here
= -1, sign_hint_here
= false;
1221 if (children_are_self_determined
)
1222 width_hint_here
= -1, sign_hint_here
= false;
1223 did_something_here
= children
[i
]->simplify(const_fold_here
, at_zero
, in_lvalue_here
, stage
, width_hint_here
, sign_hint_here
, in_param_here
);
1224 if (did_something_here
)
1225 did_something
= true;
1227 if (stage
== 2 && children
[i
]->type
== AST_INITIAL
&& current_ast_mod
!= this) {
1228 current_ast_mod
->children
.push_back(children
[i
]);
1229 children
.erase(children
.begin() + (i
--));
1230 did_something
= true;
1232 flag_autowire
= backup_flag_autowire
;
1234 for (auto &attr
: attributes
) {
1235 while (attr
.second
->simplify(true, false, false, stage
, -1, false, true))
1236 did_something
= true;
1239 if (reset_width_after_children
) {
1240 width_hint
= backup_width_hint
;
1241 sign_hint
= backup_sign_hint
;
1243 detectSignWidth(width_hint
, sign_hint
);
1246 current_block
= backup_current_block
;
1247 current_block_child
= backup_current_block_child
;
1248 current_top_block
= backup_current_top_block
;
1249 current_always
= backup_current_always
;
1250 current_always_clocked
= backup_current_always_clocked
;
1252 for (auto it
= backup_scope
.begin(); it
!= backup_scope
.end(); it
++) {
1253 if (it
->second
== NULL
)
1254 current_scope
.erase(it
->first
);
1256 current_scope
[it
->first
] = it
->second
;
1259 current_filename
= filename
;
1261 if (type
== AST_MODULE
)
1262 current_scope
.clear();
1264 // convert defparam nodes to cell parameters
1265 if (type
== AST_DEFPARAM
&& !children
.empty())
1267 if (children
[0]->type
!= AST_IDENTIFIER
)
1268 log_file_error(filename
, location
.first_line
, "Module name in defparam contains non-constant expressions!\n");
1270 string modname
, paramname
= children
[0]->str
;
1272 size_t pos
= paramname
.rfind('.');
1274 while (pos
!= 0 && pos
!= std::string::npos
)
1276 modname
= paramname
.substr(0, pos
);
1278 if (current_scope
.count(modname
))
1281 pos
= paramname
.rfind('.', pos
- 1);
1284 if (pos
== std::string::npos
)
1285 log_file_error(filename
, location
.first_line
, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname
).c_str());
1287 paramname
= "\\" + paramname
.substr(pos
+1);
1289 if (current_scope
.at(modname
)->type
!= AST_CELL
)
1290 log_file_error(filename
, location
.first_line
, "Defparam argument `%s . %s` does not match a cell!\n",
1291 RTLIL::unescape_id(modname
).c_str(), RTLIL::unescape_id(paramname
).c_str());
1293 AstNode
*paraset
= new AstNode(AST_PARASET
, children
[1]->clone(), GetSize(children
) > 2 ? children
[2]->clone() : NULL
);
1294 paraset
->str
= paramname
;
1296 AstNode
*cell
= current_scope
.at(modname
);
1297 cell
->children
.insert(cell
->children
.begin() + 1, paraset
);
1302 if (type
== AST_TYPEDEF
) {
1303 log_assert(children
.size() == 1);
1304 auto type_node
= children
[0];
1305 log_assert(type_node
->type
== AST_WIRE
|| type_node
->type
== AST_MEMORY
|| type_node
->type
== AST_STRUCT
|| type_node
->type
== AST_UNION
);
1306 while (type_node
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {
1307 did_something
= true;
1309 log_assert(!type_node
->is_custom_type
);
1312 // resolve types of wires
1313 if (type
== AST_WIRE
|| type
== AST_MEMORY
) {
1314 if (is_custom_type
) {
1315 log_assert(children
.size() >= 1);
1316 log_assert(children
[0]->type
== AST_WIRETYPE
);
1317 auto type_name
= children
[0]->str
;
1318 if (!current_scope
.count(type_name
)) {
1319 log_file_error(filename
, location
.first_line
, "Unknown identifier `%s' used as type name\n", type_name
.c_str());
1321 AstNode
*resolved_type_node
= current_scope
.at(type_name
);
1322 if (resolved_type_node
->type
!= AST_TYPEDEF
)
1323 log_file_error(filename
, location
.first_line
, "`%s' does not name a type\n", type_name
.c_str());
1324 log_assert(resolved_type_node
->children
.size() == 1);
1325 AstNode
*template_node
= resolved_type_node
->children
[0];
1327 // Ensure typedef itself is fully simplified
1328 while (template_node
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
1330 if (template_node
->type
== AST_STRUCT
|| template_node
->type
== AST_UNION
) {
1331 // replace with wire representing the packed structure
1332 newNode
= make_packed_struct(template_node
, str
);
1333 // add original input/output attribute to resolved wire
1334 newNode
->is_input
= this->is_input
;
1335 newNode
->is_output
= this->is_output
;
1336 current_scope
[str
] = this;
1340 // Remove type reference
1342 children
.erase(children
.begin());
1344 if (type
== AST_WIRE
)
1345 type
= template_node
->type
;
1346 is_reg
= template_node
->is_reg
;
1347 is_logic
= template_node
->is_logic
;
1348 is_signed
= template_node
->is_signed
;
1349 is_string
= template_node
->is_string
;
1350 is_custom_type
= template_node
->is_custom_type
;
1352 range_valid
= template_node
->range_valid
;
1353 range_swapped
= template_node
->range_swapped
;
1354 range_left
= template_node
->range_left
;
1355 range_right
= template_node
->range_right
;
1357 attributes
[ID::wiretype
] = mkconst_str(resolved_type_node
->str
);
1359 // if an enum then add attributes to support simulator tracing
1360 annotateTypedEnums(template_node
);
1362 // Insert clones children from template at beginning
1363 for (int i
= 0; i
< GetSize(template_node
->children
); i
++)
1364 children
.insert(children
.begin() + i
, template_node
->children
[i
]->clone());
1366 if (type
== AST_MEMORY
&& GetSize(children
) == 1) {
1367 // Single-bit memories must have [0:0] range
1368 AstNode
*rng
= make_range(0, 0);
1369 children
.insert(children
.begin(), rng
);
1371 did_something
= true;
1373 log_assert(!is_custom_type
);
1376 // resolve types of parameters
1377 if (type
== AST_LOCALPARAM
|| type
== AST_PARAMETER
) {
1378 if (is_custom_type
) {
1379 log_assert(children
.size() == 2);
1380 log_assert(children
[1]->type
== AST_WIRETYPE
);
1381 if (!current_scope
.count(children
[1]->str
))
1382 log_file_error(filename
, location
.first_line
, "Unknown identifier `%s' used as type name\n", children
[1]->str
.c_str());
1383 AstNode
*resolved_type_node
= current_scope
.at(children
[1]->str
);
1384 if (resolved_type_node
->type
!= AST_TYPEDEF
)
1385 log_file_error(filename
, location
.first_line
, "`%s' does not name a type\n", children
[1]->str
.c_str());
1386 log_assert(resolved_type_node
->children
.size() == 1);
1387 AstNode
*template_node
= resolved_type_node
->children
[0];
1389 children
.pop_back();
1391 // Ensure typedef itself is fully simplified
1392 while(template_node
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
1394 if (template_node
->type
== AST_MEMORY
)
1395 log_file_error(filename
, location
.first_line
, "unpacked array type `%s' cannot be used for a parameter\n", children
[1]->str
.c_str());
1396 is_signed
= template_node
->is_signed
;
1397 is_string
= template_node
->is_string
;
1398 is_custom_type
= template_node
->is_custom_type
;
1400 range_valid
= template_node
->range_valid
;
1401 range_swapped
= template_node
->range_swapped
;
1402 range_left
= template_node
->range_left
;
1403 range_right
= template_node
->range_right
;
1404 attributes
[ID::wiretype
] = mkconst_str(resolved_type_node
->str
);
1405 for (auto template_child
: template_node
->children
)
1406 children
.push_back(template_child
->clone());
1407 did_something
= true;
1409 log_assert(!is_custom_type
);
1412 // resolve constant prefixes
1413 if (type
== AST_PREFIX
) {
1414 if (children
[0]->type
!= AST_CONSTANT
) {
1415 // dumpAst(NULL, "> ");
1416 log_file_error(filename
, location
.first_line
, "Index in generate block prefix syntax is not constant!\n");
1418 if (children
[1]->type
== AST_PREFIX
)
1419 children
[1]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
);
1420 log_assert(children
[1]->type
== AST_IDENTIFIER
);
1421 newNode
= children
[1]->clone();
1422 const char *second_part
= children
[1]->str
.c_str();
1423 if (second_part
[0] == '\\')
1425 newNode
->str
= stringf("%s[%d].%s", str
.c_str(), children
[0]->integer
, second_part
);
1429 // evaluate TO_BITS nodes
1430 if (type
== AST_TO_BITS
) {
1431 if (children
[0]->type
!= AST_CONSTANT
)
1432 log_file_error(filename
, location
.first_line
, "Left operand of to_bits expression is not constant!\n");
1433 if (children
[1]->type
!= AST_CONSTANT
)
1434 log_file_error(filename
, location
.first_line
, "Right operand of to_bits expression is not constant!\n");
1435 RTLIL::Const new_value
= children
[1]->bitsAsConst(children
[0]->bitsAsConst().as_int(), children
[1]->is_signed
);
1436 newNode
= mkconst_bits(new_value
.bits
, children
[1]->is_signed
);
1440 // annotate constant ranges
1441 if (type
== AST_RANGE
) {
1442 bool old_range_valid
= range_valid
;
1443 range_valid
= false;
1444 range_swapped
= false;
1447 log_assert(children
.size() >= 1);
1448 if (children
[0]->type
== AST_CONSTANT
) {
1450 range_left
= children
[0]->integer
;
1451 if (children
.size() == 1)
1452 range_right
= range_left
;
1454 if (children
.size() >= 2) {
1455 if (children
[1]->type
== AST_CONSTANT
)
1456 range_right
= children
[1]->integer
;
1458 range_valid
= false;
1460 if (old_range_valid
!= range_valid
)
1461 did_something
= true;
1462 if (range_valid
&& range_right
> range_left
) {
1463 int tmp
= range_right
;
1464 range_right
= range_left
;
1466 range_swapped
= true;
1470 // annotate wires with their ranges
1471 if (type
== AST_WIRE
) {
1472 if (children
.size() > 0) {
1473 if (children
[0]->range_valid
) {
1475 did_something
= true;
1477 range_swapped
= children
[0]->range_swapped
;
1478 range_left
= children
[0]->range_left
;
1479 range_right
= children
[0]->range_right
;
1480 bool force_upto
= false, force_downto
= false;
1481 if (attributes
.count(ID::force_upto
)) {
1482 AstNode
*val
= attributes
[ID::force_upto
];
1483 if (val
->type
!= AST_CONSTANT
)
1484 log_file_error(filename
, location
.first_line
, "Attribute `force_upto' with non-constant value!\n");
1485 force_upto
= val
->asAttrConst().as_bool();
1487 if (attributes
.count(ID::force_downto
)) {
1488 AstNode
*val
= attributes
[ID::force_downto
];
1489 if (val
->type
!= AST_CONSTANT
)
1490 log_file_error(filename
, location
.first_line
, "Attribute `force_downto' with non-constant value!\n");
1491 force_downto
= val
->asAttrConst().as_bool();
1493 if (force_upto
&& force_downto
)
1494 log_file_error(filename
, location
.first_line
, "Attributes `force_downto' and `force_upto' cannot be both set!\n");
1495 if ((force_upto
&& !range_swapped
) || (force_downto
&& range_swapped
)) {
1496 std::swap(range_left
, range_right
);
1497 range_swapped
= force_upto
;
1502 did_something
= true;
1504 range_swapped
= false;
1510 // resolve multiranges on memory decl
1511 if (type
== AST_MEMORY
&& children
.size() > 1 && children
[1]->type
== AST_MULTIRANGE
)
1514 multirange_dimensions
.clear();
1515 multirange_swapped
.clear();
1516 for (auto range
: children
[1]->children
) {
1517 if (!range
->range_valid
)
1518 log_file_error(filename
, location
.first_line
, "Non-constant range on memory decl.\n");
1519 multirange_dimensions
.push_back(min(range
->range_left
, range
->range_right
));
1520 multirange_dimensions
.push_back(max(range
->range_left
, range
->range_right
) - min(range
->range_left
, range
->range_right
) + 1);
1521 multirange_swapped
.push_back(range
->range_swapped
);
1522 total_size
*= multirange_dimensions
.back();
1525 children
[1] = new AstNode(AST_RANGE
, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size
-1, true));
1526 did_something
= true;
1529 // resolve multiranges on memory access
1530 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
&& children
.size() > 0 && children
[0]->type
== AST_MULTIRANGE
)
1532 AstNode
*index_expr
= nullptr;
1534 integer
= children
[0]->children
.size(); // save original number of dimensions for $size() etc.
1535 for (int i
= 0; 2*i
< GetSize(id2ast
->multirange_dimensions
); i
++)
1537 if (GetSize(children
[0]->children
) <= i
)
1538 log_file_error(filename
, location
.first_line
, "Insufficient number of array indices for %s.\n", log_id(str
));
1540 AstNode
*new_index_expr
= children
[0]->children
[i
]->children
.at(0)->clone();
1542 if (id2ast
->multirange_dimensions
[2*i
])
1543 new_index_expr
= new AstNode(AST_SUB
, new_index_expr
, AstNode::mkconst_int(id2ast
->multirange_dimensions
[2*i
], true));
1546 index_expr
= new_index_expr
;
1548 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
);
1551 for (int i
= GetSize(id2ast
->multirange_dimensions
)/2; i
< GetSize(children
[0]->children
); i
++)
1552 children
.push_back(children
[0]->children
[i
]->clone());
1555 if (index_expr
== nullptr)
1556 children
.erase(children
.begin());
1558 children
[0] = new AstNode(AST_RANGE
, index_expr
);
1560 did_something
= true;
1563 // trim/extend parameters
1564 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_ENUM_ITEM
) {
1565 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
1566 if (!children
[1]->range_valid
)
1567 log_file_error(filename
, location
.first_line
, "Non-constant width range on parameter decl.\n");
1568 int width
= std::abs(children
[1]->range_left
- children
[1]->range_right
) + 1;
1569 if (children
[0]->type
== AST_REALVALUE
) {
1570 RTLIL::Const constvalue
= children
[0]->realAsConst(width
);
1571 log_file_warning(filename
, location
.first_line
, "converting real value %e to binary %s.\n",
1572 children
[0]->realvalue
, log_signal(constvalue
));
1574 children
[0] = mkconst_bits(constvalue
.bits
, sign_hint
);
1575 did_something
= true;
1577 if (children
[0]->type
== AST_CONSTANT
) {
1578 if (width
!= int(children
[0]->bits
.size())) {
1579 RTLIL::SigSpec
sig(children
[0]->bits
);
1580 sig
.extend_u0(width
, children
[0]->is_signed
);
1581 AstNode
*old_child_0
= children
[0];
1582 children
[0] = mkconst_bits(sig
.as_const().bits
, is_signed
);
1585 children
[0]->is_signed
= is_signed
;
1588 range_swapped
= children
[1]->range_swapped
;
1589 range_left
= children
[1]->range_left
;
1590 range_right
= children
[1]->range_right
;
1592 if (children
.size() > 1 && children
[1]->type
== AST_REALVALUE
&& children
[0]->type
== AST_CONSTANT
) {
1593 double as_realvalue
= children
[0]->asReal(sign_hint
);
1595 children
[0] = new AstNode(AST_REALVALUE
);
1596 children
[0]->realvalue
= as_realvalue
;
1597 did_something
= true;
1601 if (type
== AST_IDENTIFIER
&& !basic_prep
) {
1602 // check if a plausible struct member sss.mmmm
1604 if (name_has_dot(str
, sname
)) {
1605 if (current_scope
.count(str
) > 0) {
1606 auto item_node
= current_scope
[str
];
1607 if (item_node
->type
== AST_STRUCT_ITEM
) {
1608 // structure member, rewrite this node to reference the packed struct wire
1609 auto range
= make_struct_member_range(this, item_node
);
1610 newNode
= new AstNode(AST_IDENTIFIER
, range
);
1611 newNode
->str
= sname
;
1612 newNode
->basic_prep
= true;
1618 // annotate identifiers using scope resolution and create auto-wires as needed
1619 if (type
== AST_IDENTIFIER
) {
1620 if (current_scope
.count(str
) == 0) {
1621 AstNode
*current_scope_ast
= (current_ast_mod
== nullptr) ? current_ast
: current_ast_mod
;
1622 const std::string
& mod_scope
= current_scope_ast
->str
;
1623 if (str
[0] == '\\' && str
.substr(0, mod_scope
.size()) == mod_scope
) {
1624 std::string new_str
= "\\" + str
.substr(mod_scope
.size() + 1);
1625 if (current_scope
.count(new_str
)) {
1629 for (auto node
: current_scope_ast
->children
) {
1630 //log("looking at mod scope child %s\n", type2str(node->type).c_str());
1631 switch (node
->type
) {
1633 case AST_LOCALPARAM
:
1640 case AST_DPI_FUNCTION
:
1641 //log("found child %s, %s\n", type2str(node->type).c_str(), node->str.c_str());
1642 if (str
== node
->str
) {
1643 //log("add %s, type %s to scope\n", str.c_str(), type2str(node->type).c_str());
1644 current_scope
[node
->str
] = node
;
1648 current_scope
[node
->str
] = node
;
1649 for (auto enum_node
: node
->children
) {
1650 log_assert(enum_node
->type
==AST_ENUM_ITEM
);
1651 if (str
== enum_node
->str
) {
1652 //log("\nadding enum item %s to scope\n", str.c_str());
1653 current_scope
[str
] = enum_node
;
1662 if (current_scope
.count(str
) == 0) {
1663 if (current_ast_mod
== nullptr) {
1664 log_file_error(filename
, location
.first_line
, "Identifier `%s' is implicitly declared outside of a module.\n", str
.c_str());
1665 } else if (flag_autowire
|| str
== "\\$global_clock") {
1666 AstNode
*auto_wire
= new AstNode(AST_AUTOWIRE
);
1667 auto_wire
->str
= str
;
1668 current_ast_mod
->children
.push_back(auto_wire
);
1669 current_scope
[str
] = auto_wire
;
1670 did_something
= true;
1672 log_file_error(filename
, location
.first_line
, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str
.c_str());
1675 if (id2ast
!= current_scope
[str
]) {
1676 id2ast
= current_scope
[str
];
1677 did_something
= true;
1681 // split memory access with bit select to individual statements
1682 if (type
== AST_IDENTIFIER
&& children
.size() == 2 && children
[0]->type
== AST_RANGE
&& children
[1]->type
== AST_RANGE
&& !in_lvalue
)
1684 if (id2ast
== NULL
|| id2ast
->type
!= AST_MEMORY
|| children
[0]->children
.size() != 1)
1685 log_file_error(filename
, location
.first_line
, "Invalid bit-select on memory access!\n");
1687 int mem_width
, mem_size
, addr_bits
;
1688 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
1690 int data_range_left
= id2ast
->children
[0]->range_left
;
1691 int data_range_right
= id2ast
->children
[0]->range_right
;
1693 if (id2ast
->children
[0]->range_swapped
)
1694 std::swap(data_range_left
, data_range_right
);
1696 std::stringstream sstr
;
1697 sstr
<< "$mem2bits$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
1698 std::string wire_id
= sstr
.str();
1700 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
1701 wire
->str
= wire_id
;
1703 wire
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
1704 current_ast_mod
->children
.push_back(wire
);
1705 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
1707 AstNode
*data
= clone();
1708 delete data
->children
[1];
1709 data
->children
.pop_back();
1711 AstNode
*assign
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), data
);
1712 assign
->children
[0]->str
= wire_id
;
1713 assign
->children
[0]->was_checked
= true;
1717 size_t assign_idx
= 0;
1718 while (assign_idx
< current_block
->children
.size() && current_block
->children
[assign_idx
] != current_block_child
)
1720 log_assert(assign_idx
< current_block
->children
.size());
1721 current_block
->children
.insert(current_block
->children
.begin()+assign_idx
, assign
);
1722 wire
->is_reg
= true;
1726 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
1727 proc
->children
[0]->children
.push_back(assign
);
1728 current_ast_mod
->children
.push_back(proc
);
1731 newNode
= new AstNode(AST_IDENTIFIER
, children
[1]->clone());
1732 newNode
->str
= wire_id
;
1733 newNode
->integer
= integer
; // save original number of dimensions for $size() etc.
1734 newNode
->id2ast
= wire
;
1738 if (type
== AST_WHILE
)
1739 log_file_error(filename
, location
.first_line
, "While loops are only allowed in constant functions!\n");
1741 if (type
== AST_REPEAT
)
1743 AstNode
*count
= children
[0];
1744 AstNode
*body
= children
[1];
1746 // eval count expression
1747 while (count
->simplify(true, false, false, stage
, 32, true, false)) { }
1749 if (count
->type
!= AST_CONSTANT
)
1750 log_file_error(filename
, location
.first_line
, "Repeat loops outside must have constant repeat counts!\n");
1752 // convert to a block with the body repeated n times
1755 for (int i
= 0; i
< count
->bitsAsConst().as_int(); i
++)
1756 children
.insert(children
.begin(), body
->clone());
1760 did_something
= true;
1763 // unroll for loops and generate-for blocks
1764 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && children
.size() != 0)
1766 AstNode
*init_ast
= children
[0];
1767 AstNode
*while_ast
= children
[1];
1768 AstNode
*next_ast
= children
[2];
1769 AstNode
*body_ast
= children
[3];
1771 while (body_ast
->type
== AST_GENBLOCK
&& body_ast
->str
.empty() &&
1772 body_ast
->children
.size() == 1 && body_ast
->children
.at(0)->type
== AST_GENBLOCK
)
1773 body_ast
= body_ast
->children
.at(0);
1775 const char* loop_type_str
= "procedural";
1776 const char* var_type_str
= "register";
1777 AstNodeType var_type
= AST_WIRE
;
1778 if (type
== AST_GENFOR
) {
1779 loop_type_str
= "generate";
1780 var_type_str
= "genvar";
1781 var_type
= AST_GENVAR
;
1784 if (init_ast
->type
!= AST_ASSIGN_EQ
)
1785 log_file_error(filename
, location
.first_line
, "Unsupported 1st expression of %s for-loop!\n", loop_type_str
);
1786 if (next_ast
->type
!= AST_ASSIGN_EQ
)
1787 log_file_error(filename
, location
.first_line
, "Unsupported 3rd expression of %s for-loop!\n", loop_type_str
);
1789 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= var_type
)
1790 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
);
1791 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= var_type
)
1792 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
);
1794 if (init_ast
->children
[0]->id2ast
!= next_ast
->children
[0]->id2ast
)
1795 log_file_error(filename
, location
.first_line
, "Incompatible left-hand sides in 1st and 3rd expression of %s for-loop!\n", loop_type_str
);
1797 // eval 1st expression
1798 AstNode
*varbuf
= init_ast
->children
[1]->clone();
1800 int expr_width_hint
= -1;
1801 bool expr_sign_hint
= true;
1802 varbuf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1803 while (varbuf
->simplify(true, false, false, stage
, 32, true, false)) { }
1806 if (varbuf
->type
!= AST_CONSTANT
)
1807 log_file_error(filename
, location
.first_line
, "Right hand side of 1st expression of %s for-loop is not constant!\n", loop_type_str
);
1809 auto resolved
= current_scope
.at(init_ast
->children
[0]->str
);
1810 if (resolved
->range_valid
) {
1811 int const_size
= varbuf
->range_left
- varbuf
->range_right
;
1812 int resolved_size
= resolved
->range_left
- resolved
->range_right
;
1813 if (const_size
< resolved_size
) {
1814 for (int i
= const_size
; i
< resolved_size
; i
++)
1815 varbuf
->bits
.push_back(resolved
->is_signed
? varbuf
->bits
.back() : State::S0
);
1816 varbuf
->range_left
= resolved
->range_left
;
1817 varbuf
->range_right
= resolved
->range_right
;
1818 varbuf
->range_swapped
= resolved
->range_swapped
;
1819 varbuf
->range_valid
= resolved
->range_valid
;
1823 varbuf
= new AstNode(AST_LOCALPARAM
, varbuf
);
1824 varbuf
->str
= init_ast
->children
[0]->str
;
1826 AstNode
*backup_scope_varbuf
= current_scope
[varbuf
->str
];
1827 current_scope
[varbuf
->str
] = varbuf
;
1829 size_t current_block_idx
= 0;
1830 if (type
== AST_FOR
) {
1831 while (current_block_idx
< current_block
->children
.size() &&
1832 current_block
->children
[current_block_idx
] != current_block_child
)
1833 current_block_idx
++;
1838 // eval 2nd expression
1839 AstNode
*buf
= while_ast
->clone();
1841 int expr_width_hint
= -1;
1842 bool expr_sign_hint
= true;
1843 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1844 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, false)) { }
1847 if (buf
->type
!= AST_CONSTANT
)
1848 log_file_error(filename
, location
.first_line
, "2nd expression of %s for-loop is not constant!\n", loop_type_str
);
1850 if (buf
->integer
== 0) {
1857 int index
= varbuf
->children
[0]->integer
;
1858 if (body_ast
->type
== AST_GENBLOCK
)
1859 buf
= body_ast
->clone();
1861 buf
= new AstNode(AST_GENBLOCK
, body_ast
->clone());
1862 if (buf
->str
.empty()) {
1863 std::stringstream sstr
;
1864 sstr
<< "$genblock$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
1865 buf
->str
= sstr
.str();
1867 std::map
<std::string
, std::string
> name_map
;
1868 std::stringstream sstr
;
1869 sstr
<< buf
->str
<< "[" << index
<< "].";
1870 buf
->expand_genblock(varbuf
->str
, sstr
.str(), name_map
);
1872 if (type
== AST_GENFOR
) {
1873 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1874 buf
->children
[i
]->simplify(const_fold
, false, false, stage
, -1, false, false);
1875 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1878 for (size_t i
= 0; i
< buf
->children
.size(); i
++)
1879 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
->children
[i
]);
1881 buf
->children
.clear();
1884 // eval 3rd expression
1885 buf
= next_ast
->children
[1]->clone();
1887 int expr_width_hint
= -1;
1888 bool expr_sign_hint
= true;
1889 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1890 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, true)) { }
1893 if (buf
->type
!= AST_CONSTANT
)
1894 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());
1896 delete varbuf
->children
[0];
1897 varbuf
->children
[0] = buf
;
1900 if (type
== AST_FOR
) {
1901 AstNode
*buf
= next_ast
->clone();
1902 delete buf
->children
[1];
1903 buf
->children
[1] = varbuf
->children
[0]->clone();
1904 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
);
1907 current_scope
[varbuf
->str
] = backup_scope_varbuf
;
1910 did_something
= true;
1913 // check for local objects in unnamed block
1914 if (type
== AST_BLOCK
&& str
.empty())
1916 for (size_t i
= 0; i
< children
.size(); i
++)
1917 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
)
1918 log_file_error(children
[i
]->filename
, children
[i
]->location
.first_line
, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
1921 // transform block with name
1922 if (type
== AST_BLOCK
&& !str
.empty())
1924 std::map
<std::string
, std::string
> name_map
;
1925 expand_genblock(std::string(), str
+ ".", name_map
);
1927 std::vector
<AstNode
*> new_children
;
1928 for (size_t i
= 0; i
< children
.size(); i
++)
1929 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
) {
1930 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1931 current_ast_mod
->children
.push_back(children
[i
]);
1932 current_scope
[children
[i
]->str
] = children
[i
];
1934 new_children
.push_back(children
[i
]);
1936 children
.swap(new_children
);
1937 did_something
= true;
1941 // simplify unconditional generate block
1942 if (type
== AST_GENBLOCK
&& children
.size() != 0)
1945 std::map
<std::string
, std::string
> name_map
;
1946 expand_genblock(std::string(), str
+ ".", name_map
);
1949 for (size_t i
= 0; i
< children
.size(); i
++) {
1950 children
[i
]->simplify(const_fold
, false, false, stage
, -1, false, false);
1951 current_ast_mod
->children
.push_back(children
[i
]);
1955 did_something
= true;
1958 // simplify generate-if blocks
1959 if (type
== AST_GENIF
&& children
.size() != 0)
1961 AstNode
*buf
= children
[0]->clone();
1962 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1963 if (buf
->type
!= AST_CONSTANT
) {
1964 // for (auto f : log_files)
1965 // dumpAst(f, "verilog-ast> ");
1966 log_file_error(filename
, location
.first_line
, "Condition for generate if is not constant!\n");
1968 if (buf
->asBool() != 0) {
1970 buf
= children
[1]->clone();
1973 buf
= children
.size() > 2 ? children
[2]->clone() : NULL
;
1978 if (buf
->type
!= AST_GENBLOCK
)
1979 buf
= new AstNode(AST_GENBLOCK
, buf
);
1981 if (!buf
->str
.empty()) {
1982 std::map
<std::string
, std::string
> name_map
;
1983 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1986 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1987 buf
->children
[i
]->simplify(const_fold
, false, false, stage
, -1, false, false);
1988 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1991 buf
->children
.clear();
1996 did_something
= true;
1999 // simplify generate-case blocks
2000 if (type
== AST_GENCASE
&& children
.size() != 0)
2002 AstNode
*buf
= children
[0]->clone();
2003 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2004 if (buf
->type
!= AST_CONSTANT
) {
2005 // for (auto f : log_files)
2006 // dumpAst(f, "verilog-ast> ");
2007 log_file_error(filename
, location
.first_line
, "Condition for generate case is not constant!\n");
2010 bool ref_signed
= buf
->is_signed
;
2011 RTLIL::Const ref_value
= buf
->bitsAsConst();
2014 AstNode
*selected_case
= NULL
;
2015 for (size_t i
= 1; i
< children
.size(); i
++)
2017 log_assert(children
.at(i
)->type
== AST_COND
|| children
.at(i
)->type
== AST_CONDX
|| children
.at(i
)->type
== AST_CONDZ
);
2019 AstNode
*this_genblock
= NULL
;
2020 for (auto child
: children
.at(i
)->children
) {
2021 log_assert(this_genblock
== NULL
);
2022 if (child
->type
== AST_GENBLOCK
)
2023 this_genblock
= child
;
2026 for (auto child
: children
.at(i
)->children
)
2028 if (child
->type
== AST_DEFAULT
) {
2029 if (selected_case
== NULL
)
2030 selected_case
= this_genblock
;
2033 if (child
->type
== AST_GENBLOCK
)
2036 buf
= child
->clone();
2037 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, true)) { }
2038 if (buf
->type
!= AST_CONSTANT
) {
2039 // for (auto f : log_files)
2040 // dumpAst(f, "verilog-ast> ");
2041 log_file_error(filename
, location
.first_line
, "Expression in generate case is not constant!\n");
2044 bool is_selected
= RTLIL::const_eq(ref_value
, buf
->bitsAsConst(), ref_signed
&& buf
->is_signed
, ref_signed
&& buf
->is_signed
, 1).as_bool();
2048 selected_case
= this_genblock
;
2049 i
= children
.size();
2055 if (selected_case
!= NULL
)
2057 log_assert(selected_case
->type
== AST_GENBLOCK
);
2058 buf
= selected_case
->clone();
2060 if (!buf
->str
.empty()) {
2061 std::map
<std::string
, std::string
> name_map
;
2062 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
2065 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
2066 buf
->children
[i
]->simplify(const_fold
, false, false, stage
, -1, false, false);
2067 current_ast_mod
->children
.push_back(buf
->children
[i
]);
2070 buf
->children
.clear();
2075 did_something
= true;
2078 // unroll cell arrays
2079 if (type
== AST_CELLARRAY
)
2081 if (!children
.at(0)->range_valid
)
2082 log_file_error(filename
, location
.first_line
, "Non-constant array range on cell array.\n");
2084 newNode
= new AstNode(AST_GENBLOCK
);
2085 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;
2087 for (int i
= 0; i
< num
; i
++) {
2088 int idx
= children
.at(0)->range_left
> children
.at(0)->range_right
? children
.at(0)->range_right
+ i
: children
.at(0)->range_right
- i
;
2089 AstNode
*new_cell
= children
.at(1)->clone();
2090 newNode
->children
.push_back(new_cell
);
2091 new_cell
->str
+= stringf("[%d]", idx
);
2092 if (new_cell
->type
== AST_PRIMITIVE
) {
2093 log_file_error(filename
, location
.first_line
, "Cell arrays of primitives are currently not supported.\n");
2095 log_assert(new_cell
->children
.at(0)->type
== AST_CELLTYPE
);
2096 new_cell
->children
.at(0)->str
= stringf("$array:%d:%d:%s", i
, num
, new_cell
->children
.at(0)->str
.c_str());
2103 // replace primitives with assignments
2104 if (type
== AST_PRIMITIVE
)
2106 if (children
.size() < 2)
2107 log_file_error(filename
, location
.first_line
, "Insufficient number of arguments for primitive `%s'!\n", str
.c_str());
2109 std::vector
<AstNode
*> children_list
;
2110 for (auto child
: children
) {
2111 log_assert(child
->type
== AST_ARGUMENT
);
2112 log_assert(child
->children
.size() == 1);
2113 children_list
.push_back(child
->children
[0]);
2114 child
->children
.clear();
2119 if (str
== "bufif0" || str
== "bufif1" || str
== "notif0" || str
== "notif1")
2121 if (children_list
.size() != 3)
2122 log_file_error(filename
, location
.first_line
, "Invalid number of arguments for primitive `%s'!\n", str
.c_str());
2124 std::vector
<RTLIL::State
> z_const(1, RTLIL::State::Sz
);
2126 AstNode
*mux_input
= children_list
.at(1);
2127 if (str
== "notif0" || str
== "notif1") {
2128 mux_input
= new AstNode(AST_BIT_NOT
, mux_input
);
2130 AstNode
*node
= new AstNode(AST_TERNARY
, children_list
.at(2));
2131 if (str
== "bufif0") {
2132 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
2133 node
->children
.push_back(mux_input
);
2135 node
->children
.push_back(mux_input
);
2136 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
2141 children
.push_back(children_list
.at(0));
2142 children
.back()->was_checked
= true;
2143 children
.push_back(node
);
2144 did_something
= true;
2148 AstNodeType op_type
= AST_NONE
;
2149 bool invert_results
= false;
2152 op_type
= AST_BIT_AND
;
2154 op_type
= AST_BIT_AND
, invert_results
= true;
2156 op_type
= AST_BIT_OR
;
2158 op_type
= AST_BIT_OR
, invert_results
= true;
2160 op_type
= AST_BIT_XOR
;
2162 op_type
= AST_BIT_XOR
, invert_results
= true;
2166 op_type
= AST_POS
, invert_results
= true;
2167 log_assert(op_type
!= AST_NONE
);
2169 AstNode
*node
= children_list
[1];
2170 if (op_type
!= AST_POS
)
2171 for (size_t i
= 2; i
< children_list
.size(); i
++) {
2172 node
= new AstNode(op_type
, node
, children_list
[i
]);
2173 node
->location
= location
;
2176 node
= new AstNode(AST_BIT_NOT
, node
);
2180 children
.push_back(children_list
[0]);
2181 children
.back()->was_checked
= true;
2182 children
.push_back(node
);
2183 did_something
= true;
2187 // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
2188 // either a big case block that selects the correct single-bit assignment, or mask and
2189 // shift operations.
2190 if (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
)
2192 if (children
[0]->type
!= AST_IDENTIFIER
|| children
[0]->children
.size() == 0)
2193 goto skip_dynamic_range_lvalue_expansion
;
2194 if (children
[0]->children
[0]->range_valid
|| did_something
)
2195 goto skip_dynamic_range_lvalue_expansion
;
2196 if (children
[0]->id2ast
== NULL
|| children
[0]->id2ast
->type
!= AST_WIRE
)
2197 goto skip_dynamic_range_lvalue_expansion
;
2198 if (!children
[0]->id2ast
->range_valid
)
2199 goto skip_dynamic_range_lvalue_expansion
;
2201 int source_width
= children
[0]->id2ast
->range_left
- children
[0]->id2ast
->range_right
+ 1;
2202 int result_width
= 1;
2204 AstNode
*shift_expr
= NULL
;
2205 AstNode
*range
= children
[0]->children
[0];
2207 if (range
->children
.size() == 1) {
2208 shift_expr
= range
->children
[0]->clone();
2210 shift_expr
= range
->children
[1]->clone();
2211 AstNode
*left_at_zero_ast
= range
->children
[0]->clone();
2212 AstNode
*right_at_zero_ast
= range
->children
[1]->clone();
2213 while (left_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
2214 while (right_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
2215 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
2216 log_file_error(filename
, location
.first_line
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
2217 result_width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
2220 bool use_case_method
= false;
2222 if (children
[0]->id2ast
->attributes
.count(ID::nowrshmsk
)) {
2223 AstNode
*node
= children
[0]->id2ast
->attributes
.at(ID::nowrshmsk
);
2224 while (node
->simplify(true, false, false, stage
, -1, false, false)) { }
2225 if (node
->type
!= AST_CONSTANT
)
2226 log_file_error(filename
, location
.first_line
, "Non-constant value for `nowrshmsk' attribute on `%s'!\n", children
[0]->id2ast
->str
.c_str());
2227 if (node
->asAttrConst().as_bool())
2228 use_case_method
= true;
2231 if (!use_case_method
&& current_always
->detect_latch(children
[0]->str
))
2232 use_case_method
= true;
2234 if (use_case_method
)
2238 did_something
= true;
2239 newNode
= new AstNode(AST_CASE
, shift_expr
);
2240 for (int i
= 0; i
< source_width
; i
++) {
2241 int start_bit
= children
[0]->id2ast
->range_right
+ i
;
2242 int end_bit
= std::min(start_bit
+result_width
,source_width
) - 1;
2243 AstNode
*cond
= new AstNode(AST_COND
, mkconst_int(start_bit
, true));
2244 AstNode
*lvalue
= children
[0]->clone();
2245 lvalue
->delete_children();
2246 lvalue
->children
.push_back(new AstNode(AST_RANGE
,
2247 mkconst_int(end_bit
, true), mkconst_int(start_bit
, true)));
2248 cond
->children
.push_back(new AstNode(AST_BLOCK
, new AstNode(type
, lvalue
, children
[1]->clone())));
2249 newNode
->children
.push_back(cond
);
2254 // mask and shift operations, disabled for now
2256 AstNode
*wire_mask
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(source_width
-1, true), mkconst_int(0, true)));
2257 wire_mask
->str
= stringf("$bitselwrite$mask$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
2258 wire_mask
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
2259 wire_mask
->is_logic
= true;
2260 while (wire_mask
->simplify(true, false, false, 1, -1, false, false)) { }
2261 current_ast_mod
->children
.push_back(wire_mask
);
2263 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(source_width
-1, true), mkconst_int(0, true)));
2264 wire_data
->str
= stringf("$bitselwrite$data$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
2265 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
2266 wire_data
->is_logic
= true;
2267 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
2268 current_ast_mod
->children
.push_back(wire_data
);
2270 did_something
= true;
2271 newNode
= new AstNode(AST_BLOCK
);
2273 AstNode
*lvalue
= children
[0]->clone();
2274 lvalue
->delete_children();
2276 AstNode
*ref_mask
= new AstNode(AST_IDENTIFIER
);
2277 ref_mask
->str
= wire_mask
->str
;
2278 ref_mask
->id2ast
= wire_mask
;
2279 ref_mask
->was_checked
= true;
2281 AstNode
*ref_data
= new AstNode(AST_IDENTIFIER
);
2282 ref_data
->str
= wire_data
->str
;
2283 ref_data
->id2ast
= wire_data
;
2284 ref_data
->was_checked
= true;
2286 AstNode
*old_data
= lvalue
->clone();
2287 if (type
== AST_ASSIGN_LE
)
2288 old_data
->lookahead
= true;
2290 AstNode
*shamt
= shift_expr
;
2292 int shamt_width_hint
= 0;
2293 bool shamt_sign_hint
= true;
2294 shamt
->detectSignWidth(shamt_width_hint
, shamt_sign_hint
);
2296 int start_bit
= children
[0]->id2ast
->range_right
;
2297 bool use_shift
= shamt_sign_hint
;
2299 if (start_bit
!= 0) {
2300 shamt
= new AstNode(AST_SUB
, shamt
, mkconst_int(start_bit
, true));
2306 t
= mkconst_bits(std::vector
<RTLIL::State
>(result_width
, State::S1
), false);
2308 t
= new AstNode(AST_SHIFT
, t
, new AstNode(AST_NEG
, shamt
->clone()));
2310 t
= new AstNode(AST_SHIFT_LEFT
, t
, shamt
->clone());
2311 t
= new AstNode(AST_ASSIGN_EQ
, ref_mask
->clone(), t
);
2312 newNode
->children
.push_back(t
);
2314 t
= new AstNode(AST_BIT_AND
, mkconst_bits(std::vector
<RTLIL::State
>(result_width
, State::S1
), false), children
[1]->clone());
2316 t
= new AstNode(AST_SHIFT
, t
, new AstNode(AST_NEG
, shamt
));
2318 t
= new AstNode(AST_SHIFT_LEFT
, t
, shamt
);
2319 t
= new AstNode(AST_ASSIGN_EQ
, ref_data
->clone(), t
);
2320 newNode
->children
.push_back(t
);
2322 t
= new AstNode(AST_BIT_AND
, old_data
, new AstNode(AST_BIT_NOT
, ref_mask
));
2323 t
= new AstNode(AST_BIT_OR
, t
, ref_data
);
2324 t
= new AstNode(type
, lvalue
, t
);
2325 newNode
->children
.push_back(t
);
2330 skip_dynamic_range_lvalue_expansion
:;
2332 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && current_block
!= NULL
)
2334 std::stringstream sstr
;
2335 sstr
<< "$formal$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
2336 std::string id_check
= sstr
.str() + "_CHECK", id_en
= sstr
.str() + "_EN";
2338 AstNode
*wire_check
= new AstNode(AST_WIRE
);
2339 wire_check
->str
= id_check
;
2340 wire_check
->was_checked
= true;
2341 current_ast_mod
->children
.push_back(wire_check
);
2342 current_scope
[wire_check
->str
] = wire_check
;
2343 while (wire_check
->simplify(true, false, false, 1, -1, false, false)) { }
2345 AstNode
*wire_en
= new AstNode(AST_WIRE
);
2346 wire_en
->str
= id_en
;
2347 wire_en
->was_checked
= true;
2348 current_ast_mod
->children
.push_back(wire_en
);
2349 if (current_always_clocked
) {
2350 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)))));
2351 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->str
= id_en
;
2352 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->was_checked
= true;
2354 current_scope
[wire_en
->str
] = wire_en
;
2355 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
2357 AstNode
*check_defval
;
2358 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
2359 check_defval
= new AstNode(AST_REDUCE_BOOL
, children
[0]->clone());
2361 std::vector
<RTLIL::State
> x_bit
;
2362 x_bit
.push_back(RTLIL::State::Sx
);
2363 check_defval
= mkconst_bits(x_bit
, false);
2366 AstNode
*assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), check_defval
);
2367 assign_check
->children
[0]->str
= id_check
;
2368 assign_check
->children
[0]->was_checked
= true;
2370 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, 1));
2371 assign_en
->children
[0]->str
= id_en
;
2372 assign_en
->children
[0]->was_checked
= true;
2374 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
2375 default_signals
->children
.push_back(assign_check
);
2376 default_signals
->children
.push_back(assign_en
);
2377 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
2379 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
2380 assign_check
= nullptr;
2382 assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_REDUCE_BOOL
, children
[0]->clone()));
2383 assign_check
->children
[0]->str
= id_check
;
2384 assign_check
->children
[0]->was_checked
= true;
2387 if (current_always
== nullptr || current_always
->type
!= AST_INITIAL
) {
2388 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(1, false, 1));
2390 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_FCALL
));
2391 assign_en
->children
[1]->str
= "\\$initstate";
2393 assign_en
->children
[0]->str
= id_en
;
2394 assign_en
->children
[0]->was_checked
= true;
2396 newNode
= new AstNode(AST_BLOCK
);
2397 if (assign_check
!= nullptr)
2398 newNode
->children
.push_back(assign_check
);
2399 newNode
->children
.push_back(assign_en
);
2401 AstNode
*assertnode
= new AstNode(type
);
2402 assertnode
->location
= location
;
2403 assertnode
->str
= str
;
2404 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
2405 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
2406 assertnode
->children
[0]->str
= id_check
;
2407 assertnode
->children
[1]->str
= id_en
;
2408 assertnode
->attributes
.swap(attributes
);
2409 current_ast_mod
->children
.push_back(assertnode
);
2414 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && children
.size() == 1)
2416 children
.push_back(mkconst_int(1, false, 1));
2417 did_something
= true;
2420 // found right-hand side identifier for memory -> replace with memory read port
2421 if (stage
> 1 && type
== AST_IDENTIFIER
&& id2ast
!= NULL
&& id2ast
->type
== AST_MEMORY
&& !in_lvalue
&&
2422 children
.size() == 1 && children
[0]->type
== AST_RANGE
&& children
[0]->children
.size() == 1) {
2423 newNode
= new AstNode(AST_MEMRD
, children
[0]->children
[0]->clone());
2425 newNode
->id2ast
= id2ast
;
2429 // assignment with nontrivial member in left-hand concat expression -> split assignment
2430 if ((type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_CONCAT
&& width_hint
> 0)
2432 bool found_nontrivial_member
= false;
2434 for (auto child
: children
[0]->children
) {
2435 if (child
->type
== AST_IDENTIFIER
&& child
->id2ast
!= NULL
&& child
->id2ast
->type
== AST_MEMORY
)
2436 found_nontrivial_member
= true;
2439 if (found_nontrivial_member
)
2441 newNode
= new AstNode(AST_BLOCK
);
2443 AstNode
*wire_tmp
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
2444 wire_tmp
->str
= stringf("$splitcmplxassign$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
2445 current_ast_mod
->children
.push_back(wire_tmp
);
2446 current_scope
[wire_tmp
->str
] = wire_tmp
;
2447 wire_tmp
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
2448 while (wire_tmp
->simplify(true, false, false, 1, -1, false, false)) { }
2449 wire_tmp
->is_logic
= true;
2451 AstNode
*wire_tmp_id
= new AstNode(AST_IDENTIFIER
);
2452 wire_tmp_id
->str
= wire_tmp
->str
;
2454 newNode
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, wire_tmp_id
, children
[1]->clone()));
2455 newNode
->children
.back()->was_checked
= true;
2458 for (auto child
: children
[0]->children
)
2460 int child_width_hint
= -1;
2461 bool child_sign_hint
= true;
2462 child
->detectSignWidth(child_width_hint
, child_sign_hint
);
2464 AstNode
*rhs
= wire_tmp_id
->clone();
2465 rhs
->children
.push_back(new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+child_width_hint
-1, true), AstNode::mkconst_int(cursor
, true)));
2466 newNode
->children
.push_back(new AstNode(type
, child
->clone(), rhs
));
2468 cursor
+= child_width_hint
;
2475 // assignment with memory in left-hand side expression -> replace with memory write port
2476 if (stage
> 1 && (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_IDENTIFIER
&&
2477 children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
&& children
[0]->id2ast
->children
.size() >= 2 &&
2478 children
[0]->id2ast
->children
[0]->range_valid
&& children
[0]->id2ast
->children
[1]->range_valid
&&
2479 (children
[0]->children
.size() == 1 || children
[0]->children
.size() == 2) && children
[0]->children
[0]->type
== AST_RANGE
)
2481 std::stringstream sstr
;
2482 sstr
<< "$memwr$" << children
[0]->str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
2483 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA", id_en
= sstr
.str() + "_EN";
2485 int mem_width
, mem_size
, addr_bits
;
2486 bool mem_signed
= children
[0]->id2ast
->is_signed
;
2487 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
2489 newNode
= new AstNode(AST_BLOCK
);
2490 AstNode
*defNode
= new AstNode(AST_BLOCK
);
2492 int data_range_left
= children
[0]->id2ast
->children
[0]->range_left
;
2493 int data_range_right
= children
[0]->id2ast
->children
[0]->range_right
;
2494 int mem_data_range_offset
= std::min(data_range_left
, data_range_right
);
2496 int addr_width_hint
= -1;
2497 bool addr_sign_hint
= true;
2498 children
[0]->children
[0]->children
[0]->detectSignWidthWorker(addr_width_hint
, addr_sign_hint
);
2499 addr_bits
= std::max(addr_bits
, addr_width_hint
);
2501 std::vector
<RTLIL::State
> x_bits_addr
, x_bits_data
, set_bits_en
;
2502 for (int i
= 0; i
< addr_bits
; i
++)
2503 x_bits_addr
.push_back(RTLIL::State::Sx
);
2504 for (int i
= 0; i
< mem_width
; i
++)
2505 x_bits_data
.push_back(RTLIL::State::Sx
);
2506 for (int i
= 0; i
< mem_width
; i
++)
2507 set_bits_en
.push_back(RTLIL::State::S1
);
2509 AstNode
*node_addr
= nullptr;
2510 if (children
[0]->children
[0]->children
[0]->isConst()) {
2511 node_addr
= children
[0]->children
[0]->children
[0]->clone();
2513 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
2514 wire_addr
->str
= id_addr
;
2515 wire_addr
->was_checked
= true;
2516 current_ast_mod
->children
.push_back(wire_addr
);
2517 current_scope
[wire_addr
->str
] = wire_addr
;
2518 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
2520 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_addr
, false));
2521 assign_addr
->children
[0]->str
= id_addr
;
2522 assign_addr
->children
[0]->was_checked
= true;
2523 defNode
->children
.push_back(assign_addr
);
2525 assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
2526 assign_addr
->children
[0]->str
= id_addr
;
2527 assign_addr
->children
[0]->was_checked
= true;
2528 newNode
->children
.push_back(assign_addr
);
2530 node_addr
= new AstNode(AST_IDENTIFIER
);
2531 node_addr
->str
= id_addr
;
2534 AstNode
*node_data
= nullptr;
2535 if (children
[0]->children
.size() == 1 && children
[1]->isConst()) {
2536 node_data
= children
[1]->clone();
2538 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
2539 wire_data
->str
= id_data
;
2540 wire_data
->was_checked
= true;
2541 wire_data
->is_signed
= mem_signed
;
2542 current_ast_mod
->children
.push_back(wire_data
);
2543 current_scope
[wire_data
->str
] = wire_data
;
2544 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
2546 AstNode
*assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_data
, false));
2547 assign_data
->children
[0]->str
= id_data
;
2548 assign_data
->children
[0]->was_checked
= true;
2549 defNode
->children
.push_back(assign_data
);
2551 node_data
= new AstNode(AST_IDENTIFIER
);
2552 node_data
->str
= id_data
;
2555 AstNode
*node_en
= nullptr;
2556 if (current_always
->type
== AST_INITIAL
) {
2557 node_en
= AstNode::mkconst_int(1, false);
2559 AstNode
*wire_en
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
2560 wire_en
->str
= id_en
;
2561 wire_en
->was_checked
= true;
2562 current_ast_mod
->children
.push_back(wire_en
);
2563 current_scope
[wire_en
->str
] = wire_en
;
2564 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
2566 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, mem_width
));
2567 assign_en
->children
[0]->str
= id_en
;
2568 assign_en
->children
[0]->was_checked
= true;
2569 defNode
->children
.push_back(assign_en
);
2571 node_en
= new AstNode(AST_IDENTIFIER
);
2572 node_en
->str
= id_en
;
2575 if (!defNode
->children
.empty())
2576 current_top_block
->children
.insert(current_top_block
->children
.begin(), defNode
);
2580 AstNode
*assign_data
= nullptr;
2581 AstNode
*assign_en
= nullptr;
2582 if (children
[0]->children
.size() == 2)
2584 if (children
[0]->children
[1]->range_valid
)
2586 int offset
= children
[0]->children
[1]->range_right
;
2587 int width
= children
[0]->children
[1]->range_left
- offset
+ 1;
2588 offset
-= mem_data_range_offset
;
2590 std::vector
<RTLIL::State
> padding_x(offset
, RTLIL::State::Sx
);
2592 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
2593 new AstNode(AST_CONCAT
, mkconst_bits(padding_x
, false), children
[1]->clone()));
2594 assign_data
->children
[0]->str
= id_data
;
2595 assign_data
->children
[0]->was_checked
= true;
2597 if (current_always
->type
!= AST_INITIAL
) {
2598 for (int i
= 0; i
< mem_width
; i
++)
2599 set_bits_en
[i
] = offset
<= i
&& i
< offset
+width
? RTLIL::State::S1
: RTLIL::State::S0
;
2600 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
2601 assign_en
->children
[0]->str
= id_en
;
2602 assign_en
->children
[0]->was_checked
= true;
2607 AstNode
*the_range
= children
[0]->children
[1];
2608 AstNode
*left_at_zero_ast
= the_range
->children
[0]->clone();
2609 AstNode
*right_at_zero_ast
= the_range
->children
.size() >= 2 ? the_range
->children
[1]->clone() : left_at_zero_ast
->clone();
2610 AstNode
*offset_ast
= right_at_zero_ast
->clone();
2612 if (mem_data_range_offset
)
2613 offset_ast
= new AstNode(AST_SUB
, offset_ast
, mkconst_int(mem_data_range_offset
, true));
2615 while (left_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
2616 while (right_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
2617 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
2618 log_file_error(filename
, location
.first_line
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
2619 int width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
2621 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
2622 new AstNode(AST_SHIFT_LEFT
, children
[1]->clone(), offset_ast
->clone()));
2623 assign_data
->children
[0]->str
= id_data
;
2624 assign_data
->children
[0]->was_checked
= true;
2626 if (current_always
->type
!= AST_INITIAL
) {
2627 for (int i
= 0; i
< mem_width
; i
++)
2628 set_bits_en
[i
] = i
< width
? RTLIL::State::S1
: RTLIL::State::S0
;
2629 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
2630 new AstNode(AST_SHIFT_LEFT
, mkconst_bits(set_bits_en
, false), offset_ast
->clone()));
2631 assign_en
->children
[0]->str
= id_en
;
2632 assign_en
->children
[0]->was_checked
= true;
2635 delete left_at_zero_ast
;
2636 delete right_at_zero_ast
;
2642 if (!(children
[0]->children
.size() == 1 && children
[1]->isConst())) {
2643 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[1]->clone());
2644 assign_data
->children
[0]->str
= id_data
;
2645 assign_data
->children
[0]->was_checked
= true;
2648 if (current_always
->type
!= AST_INITIAL
) {
2649 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
2650 assign_en
->children
[0]->str
= id_en
;
2651 assign_en
->children
[0]->was_checked
= true;
2655 newNode
->children
.push_back(assign_data
);
2657 newNode
->children
.push_back(assign_en
);
2659 AstNode
*wrnode
= new AstNode(current_always
->type
== AST_INITIAL
? AST_MEMINIT
: AST_MEMWR
, node_addr
, node_data
, node_en
);
2660 wrnode
->str
= children
[0]->str
;
2661 wrnode
->id2ast
= children
[0]->id2ast
;
2662 current_ast_mod
->children
.push_back(wrnode
);
2664 if (newNode
->children
.empty()) {
2666 newNode
= new AstNode();
2671 // replace function and task calls with the code from the function or task
2672 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && !str
.empty())
2674 if (type
== AST_FCALL
)
2676 if (str
== "\\$initstate")
2678 int myidx
= autoidx
++;
2680 AstNode
*wire
= new AstNode(AST_WIRE
);
2681 wire
->str
= stringf("$initstate$%d_wire", myidx
);
2682 current_ast_mod
->children
.push_back(wire
);
2683 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2685 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
), new AstNode(AST_ARGUMENT
, new AstNode(AST_IDENTIFIER
)));
2686 cell
->str
= stringf("$initstate$%d", myidx
);
2687 cell
->children
[0]->str
= "$initstate";
2688 cell
->children
[1]->str
= "\\Y";
2689 cell
->children
[1]->children
[0]->str
= wire
->str
;
2690 cell
->children
[1]->children
[0]->id2ast
= wire
;
2691 current_ast_mod
->children
.push_back(cell
);
2692 while (cell
->simplify(true, false, false, 1, -1, false, false)) { }
2694 newNode
= new AstNode(AST_IDENTIFIER
);
2695 newNode
->str
= wire
->str
;
2696 newNode
->id2ast
= wire
;
2700 if (str
== "\\$past")
2703 goto replace_fcall_later
;
2707 if (GetSize(children
) != 1 && GetSize(children
) != 2)
2708 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1 or 2.\n",
2709 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2711 if (!current_always_clocked
)
2712 log_file_error(filename
, location
.first_line
, "System function %s is only allowed in clocked blocks.\n",
2713 RTLIL::unescape_id(str
).c_str());
2715 if (GetSize(children
) == 2)
2717 AstNode
*buf
= children
[1]->clone();
2718 while (buf
->simplify(true, false, false, stage
, -1, false, false)) { }
2719 if (buf
->type
!= AST_CONSTANT
)
2720 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
2722 num_steps
= buf
->asInt(true);
2726 AstNode
*block
= nullptr;
2728 for (auto child
: current_always
->children
)
2729 if (child
->type
== AST_BLOCK
)
2732 log_assert(block
!= nullptr);
2734 if (num_steps
== 0) {
2735 newNode
= children
[0]->clone();
2739 int myidx
= autoidx
++;
2740 AstNode
*outreg
= nullptr;
2742 for (int i
= 0; i
< num_steps
; i
++)
2744 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
2745 mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
2747 reg
->str
= stringf("$past$%s:%d$%d$%d", filename
.c_str(), location
.first_line
, myidx
, i
);
2750 current_ast_mod
->children
.push_back(reg
);
2752 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
2754 AstNode
*regid
= new AstNode(AST_IDENTIFIER
);
2755 regid
->str
= reg
->str
;
2756 regid
->id2ast
= reg
;
2757 regid
->was_checked
= true;
2759 AstNode
*rhs
= nullptr;
2761 if (outreg
== nullptr) {
2762 rhs
= children
.at(0)->clone();
2764 rhs
= new AstNode(AST_IDENTIFIER
);
2765 rhs
->str
= outreg
->str
;
2766 rhs
->id2ast
= outreg
;
2769 block
->children
.push_back(new AstNode(AST_ASSIGN_LE
, regid
, rhs
));
2773 newNode
= new AstNode(AST_IDENTIFIER
);
2774 newNode
->str
= outreg
->str
;
2775 newNode
->id2ast
= outreg
;
2779 if (str
== "\\$stable" || str
== "\\$rose" || str
== "\\$fell" || str
== "\\$changed")
2781 if (GetSize(children
) != 1)
2782 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2783 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2785 if (!current_always_clocked
)
2786 log_file_error(filename
, location
.first_line
, "System function %s is only allowed in clocked blocks.\n",
2787 RTLIL::unescape_id(str
).c_str());
2789 AstNode
*present
= children
.at(0)->clone();
2790 AstNode
*past
= clone();
2791 past
->str
= "\\$past";
2793 if (str
== "\\$stable")
2794 newNode
= new AstNode(AST_EQ
, past
, present
);
2796 else if (str
== "\\$changed")
2797 newNode
= new AstNode(AST_NE
, past
, present
);
2799 else if (str
== "\\$rose")
2800 newNode
= new AstNode(AST_LOGIC_AND
,
2801 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false))),
2802 new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false)));
2804 else if (str
== "\\$fell")
2805 newNode
= new AstNode(AST_LOGIC_AND
,
2806 new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false)),
2807 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false))));
2815 // $anyconst and $anyseq are mapped in AstNode::genRTLIL()
2816 if (str
== "\\$anyconst" || str
== "\\$anyseq" || str
== "\\$allconst" || str
== "\\$allseq") {
2817 recursion_counter
--;
2821 if (str
== "\\$clog2")
2823 if (children
.size() != 1)
2824 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2825 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2827 AstNode
*buf
= children
[0]->clone();
2828 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2829 if (buf
->type
!= AST_CONSTANT
)
2830 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
2832 RTLIL::Const arg_value
= buf
->bitsAsConst();
2833 if (arg_value
.as_bool())
2834 arg_value
= const_sub(arg_value
, 1, false, false, GetSize(arg_value
));
2837 uint32_t result
= 0;
2838 for (size_t i
= 0; i
< arg_value
.bits
.size(); i
++)
2839 if (arg_value
.bits
.at(i
) == RTLIL::State::S1
)
2842 newNode
= mkconst_int(result
, true);
2846 if (str
== "\\$size" || str
== "\\$bits" || str
== "\\$high" || str
== "\\$low" || str
== "\\$left" || str
== "\\$right")
2849 if (str
== "\\$bits") {
2850 if (children
.size() != 1)
2851 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2852 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2854 if (children
.size() != 1 && children
.size() != 2)
2855 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1 or 2.\n",
2856 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2857 if (children
.size() == 2) {
2858 AstNode
*buf
= children
[1]->clone();
2859 // Evaluate constant expression
2860 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2861 dim
= buf
->asInt(false);
2865 AstNode
*buf
= children
[0]->clone();
2867 int result
, high
= 0, low
= 0, left
= 0, right
= 0, width
= 1; // defaults for a simple wire
2868 AstNode
*id_ast
= NULL
;
2871 //while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2872 buf
->detectSignWidth(width_hint
, sign_hint
);
2874 if (buf
->type
== AST_IDENTIFIER
) {
2875 id_ast
= buf
->id2ast
;
2876 if (id_ast
== NULL
&& current_scope
.count(buf
->str
))
2877 id_ast
= current_scope
.at(buf
->str
);
2879 log_file_error(filename
, location
.first_line
, "Failed to resolve identifier %s for width detection!\n", buf
->str
.c_str());
2880 // a slice of our identifier means we advance to the next dimension, e.g. $size(a[3])
2881 if (buf
->children
.size() > 0) {
2882 // something is hanging below this identifier
2883 if (buf
->children
[0]->type
== AST_RANGE
&& buf
->integer
== 0)
2884 // if integer == 0, this node was originally created as AST_RANGE so it's dimension is 1
2886 // more than one range, e.g. $size(a[3][2])
2887 else // created an AST_MULTIRANGE, converted to AST_RANGE, but original dimension saved in 'integer' field
2888 dim
+= buf
->integer
; // increment by multirange size
2891 // wire x; ==> AST_WIRE, no AST_RANGE children
2892 // wire [1:0]x; ==> AST_WIRE, AST_RANGE children
2893 // wire [1:0]x[1:0]; ==> AST_MEMORY, two AST_RANGE children (1st for packed, 2nd for unpacked)
2894 // wire [1:0]x[1:0][1:0]; ==> AST_MEMORY, one AST_RANGE child (0) for packed, then AST_MULTIRANGE child (1) for unpacked
2895 // (updated: actually by the time we are here, AST_MULTIRANGE is converted into one big AST_RANGE)
2896 // case 0 handled by default
2897 if ((id_ast
->type
== AST_WIRE
|| id_ast
->type
== AST_MEMORY
) && id_ast
->children
.size() > 0) {
2898 // handle packed array left/right for case 1, and cases 2/3 when requesting the last dimension (packed side)
2899 AstNode
*wire_range
= id_ast
->children
[0];
2900 left
= wire_range
->children
[0]->integer
;
2901 right
= wire_range
->children
[1]->integer
;
2902 high
= max(left
, right
);
2903 low
= min(left
, right
);
2905 if (id_ast
->type
== AST_MEMORY
) {
2906 // We got here only if the argument is a memory
2907 // Otherwise $size() and $bits() return the expression width
2908 AstNode
*mem_range
= id_ast
->children
[1];
2909 if (str
== "\\$bits") {
2910 if (mem_range
->type
== AST_RANGE
) {
2911 if (!mem_range
->range_valid
)
2912 log_file_error(filename
, location
.first_line
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2913 mem_depth
= mem_range
->range_left
- mem_range
->range_right
+ 1;
2915 log_file_error(filename
, location
.first_line
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2917 // $size(), $left(), $right(), $high(), $low()
2919 if (mem_range
->type
== AST_RANGE
) {
2920 if (id_ast
->multirange_dimensions
.empty()) {
2921 if (!mem_range
->range_valid
)
2922 log_file_error(filename
, location
.first_line
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2924 left
= mem_range
->range_right
;
2925 right
= mem_range
->range_left
;
2926 high
= max(left
, right
);
2927 low
= min(left
, right
);
2930 dims
= GetSize(id_ast
->multirange_dimensions
)/2;
2932 width_hint
= id_ast
->multirange_dimensions
[2*dim
-1];
2933 high
= id_ast
->multirange_dimensions
[2*dim
-2] + id_ast
->multirange_dimensions
[2*dim
-1] - 1;
2934 low
= id_ast
->multirange_dimensions
[2*dim
-2];
2935 if (id_ast
->multirange_swapped
[dim
-1]) {
2942 } else if ((dim
> dims
+1) || (dim
< 0))
2943 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);
2946 log_file_error(filename
, location
.first_line
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2950 width
= high
- low
+ 1;
2955 if (str
== "\\$high")
2957 else if (str
== "\\$low")
2959 else if (str
== "\\$left")
2961 else if (str
== "\\$right")
2963 else if (str
== "\\$size")
2966 result
= width
* mem_depth
;
2968 newNode
= mkconst_int(result
, false);
2972 if (str
== "\\$ln" || str
== "\\$log10" || str
== "\\$exp" || str
== "\\$sqrt" || str
== "\\$pow" ||
2973 str
== "\\$floor" || str
== "\\$ceil" || str
== "\\$sin" || str
== "\\$cos" || str
== "\\$tan" ||
2974 str
== "\\$asin" || str
== "\\$acos" || str
== "\\$atan" || str
== "\\$atan2" || str
== "\\$hypot" ||
2975 str
== "\\$sinh" || str
== "\\$cosh" || str
== "\\$tanh" || str
== "\\$asinh" || str
== "\\$acosh" || str
== "\\$atanh" ||
2976 str
== "\\$rtoi" || str
== "\\$itor")
2978 bool func_with_two_arguments
= str
== "\\$pow" || str
== "\\$atan2" || str
== "\\$hypot";
2979 double x
= 0, y
= 0;
2981 if (func_with_two_arguments
) {
2982 if (children
.size() != 2)
2983 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 2.\n",
2984 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2986 if (children
.size() != 1)
2987 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2988 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2991 if (children
.size() >= 1) {
2992 while (children
[0]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2993 if (!children
[0]->isConst())
2994 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant argument.\n",
2995 RTLIL::unescape_id(str
).c_str());
2996 int child_width_hint
= width_hint
;
2997 bool child_sign_hint
= sign_hint
;
2998 children
[0]->detectSignWidth(child_width_hint
, child_sign_hint
);
2999 x
= children
[0]->asReal(child_sign_hint
);
3002 if (children
.size() >= 2) {
3003 while (children
[1]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
3004 if (!children
[1]->isConst())
3005 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant argument.\n",
3006 RTLIL::unescape_id(str
).c_str());
3007 int child_width_hint
= width_hint
;
3008 bool child_sign_hint
= sign_hint
;
3009 children
[1]->detectSignWidth(child_width_hint
, child_sign_hint
);
3010 y
= children
[1]->asReal(child_sign_hint
);
3013 if (str
== "\\$rtoi") {
3014 newNode
= AstNode::mkconst_int(x
, true);
3016 newNode
= new AstNode(AST_REALVALUE
);
3017 if (str
== "\\$ln") newNode
->realvalue
= ::log(x
);
3018 else if (str
== "\\$log10") newNode
->realvalue
= ::log10(x
);
3019 else if (str
== "\\$exp") newNode
->realvalue
= ::exp(x
);
3020 else if (str
== "\\$sqrt") newNode
->realvalue
= ::sqrt(x
);
3021 else if (str
== "\\$pow") newNode
->realvalue
= ::pow(x
, y
);
3022 else if (str
== "\\$floor") newNode
->realvalue
= ::floor(x
);
3023 else if (str
== "\\$ceil") newNode
->realvalue
= ::ceil(x
);
3024 else if (str
== "\\$sin") newNode
->realvalue
= ::sin(x
);
3025 else if (str
== "\\$cos") newNode
->realvalue
= ::cos(x
);
3026 else if (str
== "\\$tan") newNode
->realvalue
= ::tan(x
);
3027 else if (str
== "\\$asin") newNode
->realvalue
= ::asin(x
);
3028 else if (str
== "\\$acos") newNode
->realvalue
= ::acos(x
);
3029 else if (str
== "\\$atan") newNode
->realvalue
= ::atan(x
);
3030 else if (str
== "\\$atan2") newNode
->realvalue
= ::atan2(x
, y
);
3031 else if (str
== "\\$hypot") newNode
->realvalue
= ::hypot(x
, y
);
3032 else if (str
== "\\$sinh") newNode
->realvalue
= ::sinh(x
);
3033 else if (str
== "\\$cosh") newNode
->realvalue
= ::cosh(x
);
3034 else if (str
== "\\$tanh") newNode
->realvalue
= ::tanh(x
);
3035 else if (str
== "\\$asinh") newNode
->realvalue
= ::asinh(x
);
3036 else if (str
== "\\$acosh") newNode
->realvalue
= ::acosh(x
);
3037 else if (str
== "\\$atanh") newNode
->realvalue
= ::atanh(x
);
3038 else if (str
== "\\$itor") newNode
->realvalue
= x
;
3044 if (str
== "\\$sformatf") {
3045 AstNode
*node_string
= children
[0];
3046 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
3047 if (node_string
->type
!= AST_CONSTANT
)
3048 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
3049 std::string sformat
= node_string
->bitsAsConst().decode_string();
3050 std::string sout
= process_format_str(sformat
, 1, stage
, width_hint
, sign_hint
);
3051 newNode
= AstNode::mkconst_str(sout
);
3055 if (current_scope
.count(str
) != 0 && current_scope
[str
]->type
== AST_DPI_FUNCTION
)
3057 AstNode
*dpi_decl
= current_scope
[str
];
3059 std::string rtype
, fname
;
3060 std::vector
<std::string
> argtypes
;
3061 std::vector
<AstNode
*> args
;
3063 rtype
= RTLIL::unescape_id(dpi_decl
->children
.at(0)->str
);
3064 fname
= RTLIL::unescape_id(dpi_decl
->children
.at(1)->str
);
3066 for (int i
= 2; i
< GetSize(dpi_decl
->children
); i
++)
3068 if (i
-2 >= GetSize(children
))
3069 log_file_error(filename
, location
.first_line
, "Insufficient number of arguments in DPI function call.\n");
3071 argtypes
.push_back(RTLIL::unescape_id(dpi_decl
->children
.at(i
)->str
));
3072 args
.push_back(children
.at(i
-2)->clone());
3073 while (args
.back()->simplify(true, false, false, stage
, -1, false, true)) { }
3075 if (args
.back()->type
!= AST_CONSTANT
&& args
.back()->type
!= AST_REALVALUE
)
3076 log_file_error(filename
, location
.first_line
, "Failed to evaluate DPI function with non-constant argument.\n");
3079 newNode
= dpi_call(rtype
, fname
, argtypes
, args
);
3081 for (auto arg
: args
)
3087 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_FUNCTION
)
3088 log_file_error(filename
, location
.first_line
, "Can't resolve function name `%s'.\n", str
.c_str());
3091 if (type
== AST_TCALL
)
3093 if (str
== "$finish" || str
== "$stop")
3095 if (!current_always
|| current_always
->type
!= AST_INITIAL
)
3096 log_file_error(filename
, location
.first_line
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
3098 log_file_error(filename
, location
.first_line
, "System task `%s' executed.\n", str
.c_str());
3101 if (str
== "\\$readmemh" || str
== "\\$readmemb")
3103 if (GetSize(children
) < 2 || GetSize(children
) > 4)
3104 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 2-4.\n",
3105 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
3107 AstNode
*node_filename
= children
[0]->clone();
3108 while (node_filename
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
3109 if (node_filename
->type
!= AST_CONSTANT
)
3110 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
3112 AstNode
*node_memory
= children
[1]->clone();
3113 while (node_memory
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
3114 if (node_memory
->type
!= AST_IDENTIFIER
|| node_memory
->id2ast
== nullptr || node_memory
->id2ast
->type
!= AST_MEMORY
)
3115 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str
.c_str());
3117 int start_addr
= -1, finish_addr
= -1;
3119 if (GetSize(children
) > 2) {
3120 AstNode
*node_addr
= children
[2]->clone();
3121 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
3122 if (node_addr
->type
!= AST_CONSTANT
)
3123 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str
.c_str());
3124 start_addr
= int(node_addr
->asInt(false));
3127 if (GetSize(children
) > 3) {
3128 AstNode
*node_addr
= children
[3]->clone();
3129 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
3130 if (node_addr
->type
!= AST_CONSTANT
)
3131 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str
.c_str());
3132 finish_addr
= int(node_addr
->asInt(false));
3135 bool unconditional_init
= false;
3136 if (current_always
->type
== AST_INITIAL
) {
3137 pool
<AstNode
*> queue
;
3138 log_assert(current_always
->children
[0]->type
== AST_BLOCK
);
3139 queue
.insert(current_always
->children
[0]);
3140 while (!unconditional_init
&& !queue
.empty()) {
3141 pool
<AstNode
*> next_queue
;
3142 for (auto n
: queue
)
3143 for (auto c
: n
->children
) {
3145 unconditional_init
= true;
3146 next_queue
.insert(c
);
3148 next_queue
.swap(queue
);
3152 newNode
= readmem(str
== "\\$readmemh", node_filename
->bitsAsConst().decode_string(), node_memory
->id2ast
, start_addr
, finish_addr
, unconditional_init
);
3153 delete node_filename
;
3158 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_TASK
)
3159 log_file_error(filename
, location
.first_line
, "Can't resolve task name `%s'.\n", str
.c_str());
3162 AstNode
*decl
= current_scope
[str
];
3164 std::stringstream sstr
;
3165 sstr
<< "$func$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++) << "$";
3166 std::string prefix
= sstr
.str();
3168 bool recommend_const_eval
= false;
3169 bool require_const_eval
= in_param
? false : has_const_only_constructs(recommend_const_eval
);
3170 if ((in_param
|| recommend_const_eval
|| require_const_eval
) && !decl
->attributes
.count(ID::via_celltype
))
3172 bool all_args_const
= true;
3173 for (auto child
: children
) {
3174 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
3175 if (child
->type
!= AST_CONSTANT
&& child
->type
!= AST_REALVALUE
)
3176 all_args_const
= false;
3179 if (all_args_const
) {
3180 AstNode
*func_workspace
= current_scope
[str
]->clone();
3181 func_workspace
->str
= NEW_ID
.str();
3182 func_workspace
->replace_result_wire_name_in_function(str
, func_workspace
->str
);
3183 newNode
= func_workspace
->eval_const_function(this);
3184 delete func_workspace
;
3189 log_file_error(filename
, location
.first_line
, "Non-constant function call in constant expression.\n");
3190 if (require_const_eval
)
3191 log_file_error(filename
, location
.first_line
, "Function %s can only be called with constant arguments.\n", str
.c_str());
3194 size_t arg_count
= 0;
3195 std::map
<std::string
, std::string
> replace_rules
;
3196 vector
<AstNode
*> added_mod_children
;
3197 dict
<std::string
, AstNode
*> wire_cache
;
3198 vector
<AstNode
*> new_stmts
;
3199 vector
<AstNode
*> output_assignments
;
3201 if (current_block
== NULL
)
3203 log_assert(type
== AST_FCALL
);
3205 AstNode
*wire
= NULL
;
3206 for (auto child
: decl
->children
)
3207 if (child
->type
== AST_WIRE
&& child
->str
== str
)
3208 wire
= child
->clone();
3209 log_assert(wire
!= NULL
);
3211 wire
->str
= prefix
+ str
;
3213 wire
->is_input
= false;
3214 wire
->is_output
= false;
3216 current_ast_mod
->children
.push_back(wire
);
3217 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
3219 AstNode
*lvalue
= new AstNode(AST_IDENTIFIER
);
3220 lvalue
->str
= wire
->str
;
3222 AstNode
*always
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
,
3223 new AstNode(AST_ASSIGN_EQ
, lvalue
, clone())));
3224 always
->children
[0]->children
[0]->was_checked
= true;
3226 current_ast_mod
->children
.push_back(always
);
3228 goto replace_fcall_with_id
;
3231 if (decl
->attributes
.count(ID::via_celltype
))
3233 std::string celltype
= decl
->attributes
.at(ID::via_celltype
)->asAttrConst().decode_string();
3234 std::string outport
= str
;
3236 if (celltype
.find(' ') != std::string::npos
) {
3237 int pos
= celltype
.find(' ');
3238 outport
= RTLIL::escape_id(celltype
.substr(pos
+1));
3239 celltype
= RTLIL::escape_id(celltype
.substr(0, pos
));
3241 celltype
= RTLIL::escape_id(celltype
);
3243 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
));
3244 cell
->str
= prefix
.substr(0, GetSize(prefix
)-1);
3245 cell
->children
[0]->str
= celltype
;
3247 for (auto attr
: decl
->attributes
)
3248 if (attr
.first
.str().rfind("\\via_celltype_defparam_", 0) == 0)
3250 AstNode
*cell_arg
= new AstNode(AST_PARASET
, attr
.second
->clone());
3251 cell_arg
->str
= RTLIL::escape_id(attr
.first
.substr(strlen("\\via_celltype_defparam_")));
3252 cell
->children
.push_back(cell_arg
);
3255 for (auto child
: decl
->children
)
3256 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
|| (type
== AST_FCALL
&& child
->str
== str
)))
3258 AstNode
*wire
= child
->clone();
3259 wire
->str
= prefix
+ wire
->str
;
3261 wire
->is_input
= false;
3262 wire
->is_output
= false;
3263 current_ast_mod
->children
.push_back(wire
);
3264 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
3266 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
3267 wire_id
->str
= wire
->str
;
3269 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
3271 AstNode
*arg
= children
[arg_count
++]->clone();
3272 AstNode
*assign
= child
->is_input
?
3273 new AstNode(AST_ASSIGN_EQ
, wire_id
->clone(), arg
) :
3274 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
->clone());
3275 assign
->children
[0]->was_checked
= true;
3277 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
3278 if (*it
!= current_block_child
)
3280 current_block
->children
.insert(it
, assign
);
3285 AstNode
*cell_arg
= new AstNode(AST_ARGUMENT
, wire_id
);
3286 cell_arg
->str
= child
->str
== str
? outport
: child
->str
;
3287 cell
->children
.push_back(cell_arg
);
3290 current_ast_mod
->children
.push_back(cell
);
3291 goto replace_fcall_with_id
;
3294 for (auto child
: decl
->children
)
3295 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
|| child
->type
== AST_ENUM_ITEM
)
3297 AstNode
*wire
= nullptr;
3299 if (wire_cache
.count(child
->str
))
3301 wire
= wire_cache
.at(child
->str
);
3302 bool contains_value
= wire
->type
== AST_LOCALPARAM
;
3303 if (wire
->children
.size() == contains_value
) {
3304 for (auto c
: child
->children
)
3305 wire
->children
.push_back(c
->clone());
3306 } else if (!child
->children
.empty()) {
3307 while (child
->simplify(true, false, false, stage
, -1, false, false)) { }
3308 if (GetSize(child
->children
) == GetSize(wire
->children
) - contains_value
) {
3309 for (int i
= 0; i
< GetSize(child
->children
); i
++)
3310 if (*child
->children
.at(i
) != *wire
->children
.at(i
+ contains_value
))
3311 goto tcall_incompatible_wires
;
3313 tcall_incompatible_wires
:
3314 log_file_error(filename
, location
.first_line
, "Incompatible re-declaration of wire %s.\n", child
->str
.c_str());
3320 wire
= child
->clone();
3321 wire
->str
= prefix
+ wire
->str
;
3323 wire
->is_input
= false;
3324 wire
->is_output
= false;
3325 wire
->is_reg
= true;
3326 wire
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
3327 if (child
->type
== AST_ENUM_ITEM
)
3328 wire
->attributes
[ID::enum_base_type
] = child
->attributes
[ID::enum_base_type
];
3330 wire_cache
[child
->str
] = wire
;
3332 current_ast_mod
->children
.push_back(wire
);
3333 added_mod_children
.push_back(wire
);
3336 if (child
->type
== AST_WIRE
)
3337 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
3339 replace_rules
[child
->str
] = wire
->str
;
3340 current_scope
[wire
->str
] = wire
;
3342 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
3344 AstNode
*arg
= children
[arg_count
++]->clone();
3345 // convert purely constant arguments into localparams
3346 if (child
->is_input
&& child
->type
== AST_WIRE
&& arg
->type
== AST_CONSTANT
&& node_contains_assignment_to(decl
, child
)) {
3347 wire
->type
= AST_LOCALPARAM
;
3348 wire
->attributes
.erase(ID::nosync
);
3349 wire
->children
.insert(wire
->children
.begin(), arg
->clone());
3350 // args without a range implicitly have width 1
3351 if (wire
->children
.back()->type
!= AST_RANGE
) {
3352 // check if this wire is redeclared with an explicit size
3353 bool uses_explicit_size
= false;
3354 for (const AstNode
*other_child
: decl
->children
)
3355 if (other_child
->type
== AST_WIRE
&& child
->str
== other_child
->str
3356 && !other_child
->children
.empty()
3357 && other_child
->children
.back()->type
== AST_RANGE
) {
3358 uses_explicit_size
= true;
3361 if (!uses_explicit_size
) {
3362 AstNode
* range
= new AstNode();
3363 range
->type
= AST_RANGE
;
3364 wire
->children
.push_back(range
);
3365 range
->children
.push_back(mkconst_int(0, true));
3366 range
->children
.push_back(mkconst_int(0, true));
3371 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
3372 wire_id
->str
= wire
->str
;
3373 AstNode
*assign
= child
->is_input
?
3374 new AstNode(AST_ASSIGN_EQ
, wire_id
, arg
) :
3375 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
);
3376 assign
->children
[0]->was_checked
= true;
3377 if (child
->is_input
)
3378 new_stmts
.push_back(assign
);
3380 output_assignments
.push_back(assign
);
3384 for (auto child
: added_mod_children
) {
3385 child
->replace_ids(prefix
, replace_rules
);
3386 while (child
->simplify(true, false, false, 1, -1, false, false)) { }
3389 for (auto child
: decl
->children
)
3390 if (child
->type
!= AST_WIRE
&& child
->type
!= AST_MEMORY
&& child
->type
!= AST_PARAMETER
&& child
->type
!= AST_LOCALPARAM
)
3392 AstNode
*stmt
= child
->clone();
3393 stmt
->replace_ids(prefix
, replace_rules
);
3394 new_stmts
.push_back(stmt
);
3397 new_stmts
.insert(new_stmts
.end(), output_assignments
.begin(), output_assignments
.end());
3399 for (auto it
= current_block
->children
.begin(); ; it
++) {
3400 log_assert(it
!= current_block
->children
.end());
3401 if (*it
== current_block_child
) {
3402 current_block
->children
.insert(it
, new_stmts
.begin(), new_stmts
.end());
3407 replace_fcall_with_id
:
3408 if (type
== AST_FCALL
) {
3410 type
= AST_IDENTIFIER
;
3413 if (type
== AST_TCALL
)
3415 did_something
= true;
3418 replace_fcall_later
:;
3420 // perform const folding when activated
3424 std::vector
<RTLIL::State
> tmp_bits
;
3425 RTLIL::Const (*const_func
)(const RTLIL::Const
&, const RTLIL::Const
&, bool, bool, int);
3426 RTLIL::Const dummy_arg
;
3430 case AST_IDENTIFIER
:
3431 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
)) {
3432 if (current_scope
[str
]->children
[0]->type
== AST_CONSTANT
) {
3433 if (children
.size() != 0 && children
[0]->type
== AST_RANGE
&& children
[0]->range_valid
) {
3434 std::vector
<RTLIL::State
> data
;
3435 bool param_upto
= current_scope
[str
]->range_valid
&& current_scope
[str
]->range_swapped
;
3436 int param_offset
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_right
: 0;
3437 int param_width
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_left
- current_scope
[str
]->range_right
+ 1 :
3438 GetSize(current_scope
[str
]->children
[0]->bits
);
3439 int tmp_range_left
= children
[0]->range_left
, tmp_range_right
= children
[0]->range_right
;
3441 tmp_range_left
= (param_width
+ 2*param_offset
) - children
[0]->range_right
- 1;
3442 tmp_range_right
= (param_width
+ 2*param_offset
) - children
[0]->range_left
- 1;
3444 for (int i
= tmp_range_right
; i
<= tmp_range_left
; i
++) {
3445 int index
= i
- param_offset
;
3446 if (0 <= index
&& index
< param_width
)
3447 data
.push_back(current_scope
[str
]->children
[0]->bits
[index
]);
3449 data
.push_back(RTLIL::State::Sx
);
3451 newNode
= mkconst_bits(data
, false);
3453 if (children
.size() == 0)
3454 newNode
= current_scope
[str
]->children
[0]->clone();
3456 if (current_scope
[str
]->children
[0]->isConst())
3457 newNode
= current_scope
[str
]->children
[0]->clone();
3459 else if (at_zero
&& current_scope
.count(str
) > 0) {
3460 AstNode
*node
= current_scope
[str
];
3461 if (node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_MEMORY
)
3462 newNode
= mkconst_int(0, sign_hint
, width_hint
);
3467 newNode
= mkconst_int(0, sign_hint
, width_hint
);
3471 if (children
[0]->type
== AST_CONSTANT
) {
3472 RTLIL::Const y
= RTLIL::const_not(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
3473 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3477 case AST_TO_UNSIGNED
:
3478 if (children
[0]->type
== AST_CONSTANT
) {
3479 RTLIL::Const y
= children
[0]->bitsAsConst(width_hint
, sign_hint
);
3480 newNode
= mkconst_bits(y
.bits
, type
== AST_TO_SIGNED
);
3483 if (0) { case AST_BIT_AND
: const_func
= RTLIL::const_and
; }
3484 if (0) { case AST_BIT_OR
: const_func
= RTLIL::const_or
; }
3485 if (0) { case AST_BIT_XOR
: const_func
= RTLIL::const_xor
; }
3486 if (0) { case AST_BIT_XNOR
: const_func
= RTLIL::const_xnor
; }
3487 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3488 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3489 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
3490 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3493 if (0) { case AST_REDUCE_AND
: const_func
= RTLIL::const_reduce_and
; }
3494 if (0) { case AST_REDUCE_OR
: const_func
= RTLIL::const_reduce_or
; }
3495 if (0) { case AST_REDUCE_XOR
: const_func
= RTLIL::const_reduce_xor
; }
3496 if (0) { case AST_REDUCE_XNOR
: const_func
= RTLIL::const_reduce_xnor
; }
3497 if (0) { case AST_REDUCE_BOOL
: const_func
= RTLIL::const_reduce_bool
; }
3498 if (children
[0]->type
== AST_CONSTANT
) {
3499 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), dummy_arg
, false, false, -1);
3500 newNode
= mkconst_bits(y
.bits
, false);
3504 if (children
[0]->type
== AST_CONSTANT
) {
3505 RTLIL::Const y
= RTLIL::const_logic_not(RTLIL::Const(children
[0]->bits
), dummy_arg
, children
[0]->is_signed
, false, -1);
3506 newNode
= mkconst_bits(y
.bits
, false);
3508 if (children
[0]->isConst()) {
3509 newNode
= mkconst_int(children
[0]->asReal(sign_hint
) == 0, false, 1);
3512 if (0) { case AST_LOGIC_AND
: const_func
= RTLIL::const_logic_and
; }
3513 if (0) { case AST_LOGIC_OR
: const_func
= RTLIL::const_logic_or
; }
3514 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3515 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), RTLIL::Const(children
[1]->bits
),
3516 children
[0]->is_signed
, children
[1]->is_signed
, -1);
3517 newNode
= mkconst_bits(y
.bits
, false);
3519 if (children
[0]->isConst() && children
[1]->isConst()) {
3520 if (type
== AST_LOGIC_AND
)
3521 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) && (children
[1]->asReal(sign_hint
) != 0), false, 1);
3523 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) || (children
[1]->asReal(sign_hint
) != 0), false, 1);
3526 if (0) { case AST_SHIFT_LEFT
: const_func
= RTLIL::const_shl
; }
3527 if (0) { case AST_SHIFT_RIGHT
: const_func
= RTLIL::const_shr
; }
3528 if (0) { case AST_SHIFT_SLEFT
: const_func
= RTLIL::const_sshl
; }
3529 if (0) { case AST_SHIFT_SRIGHT
: const_func
= RTLIL::const_sshr
; }
3530 if (0) { case AST_POW
: const_func
= RTLIL::const_pow
; }
3531 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3532 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3533 RTLIL::Const(children
[1]->bits
), sign_hint
, type
== AST_POW
? children
[1]->is_signed
: false, width_hint
);
3534 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3536 if (type
== AST_POW
&& children
[0]->isConst() && children
[1]->isConst()) {
3537 newNode
= new AstNode(AST_REALVALUE
);
3538 newNode
->realvalue
= pow(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
));
3541 if (0) { case AST_LT
: const_func
= RTLIL::const_lt
; }
3542 if (0) { case AST_LE
: const_func
= RTLIL::const_le
; }
3543 if (0) { case AST_EQ
: const_func
= RTLIL::const_eq
; }
3544 if (0) { case AST_NE
: const_func
= RTLIL::const_ne
; }
3545 if (0) { case AST_EQX
: const_func
= RTLIL::const_eqx
; }
3546 if (0) { case AST_NEX
: const_func
= RTLIL::const_nex
; }
3547 if (0) { case AST_GE
: const_func
= RTLIL::const_ge
; }
3548 if (0) { case AST_GT
: const_func
= RTLIL::const_gt
; }
3549 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3550 int cmp_width
= max(children
[0]->bits
.size(), children
[1]->bits
.size());
3551 bool cmp_signed
= children
[0]->is_signed
&& children
[1]->is_signed
;
3552 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(cmp_width
, cmp_signed
),
3553 children
[1]->bitsAsConst(cmp_width
, cmp_signed
), cmp_signed
, cmp_signed
, 1);
3554 newNode
= mkconst_bits(y
.bits
, false);
3556 if (children
[0]->isConst() && children
[1]->isConst()) {
3557 bool cmp_signed
= (children
[0]->type
== AST_REALVALUE
|| children
[0]->is_signed
) && (children
[1]->type
== AST_REALVALUE
|| children
[1]->is_signed
);
3559 case AST_LT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) < children
[1]->asReal(cmp_signed
), false, 1); break;
3560 case AST_LE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) <= children
[1]->asReal(cmp_signed
), false, 1); break;
3561 case AST_EQ
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
3562 case AST_NE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
3563 case AST_EQX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
3564 case AST_NEX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
3565 case AST_GE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) >= children
[1]->asReal(cmp_signed
), false, 1); break;
3566 case AST_GT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) > children
[1]->asReal(cmp_signed
), false, 1); break;
3567 default: log_abort();
3571 if (0) { case AST_ADD
: const_func
= RTLIL::const_add
; }
3572 if (0) { case AST_SUB
: const_func
= RTLIL::const_sub
; }
3573 if (0) { case AST_MUL
: const_func
= RTLIL::const_mul
; }
3574 if (0) { case AST_DIV
: const_func
= RTLIL::const_div
; }
3575 if (0) { case AST_MOD
: const_func
= RTLIL::const_mod
; }
3576 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3577 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3578 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
3579 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3581 if (children
[0]->isConst() && children
[1]->isConst()) {
3582 newNode
= new AstNode(AST_REALVALUE
);
3584 case AST_ADD
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) + children
[1]->asReal(sign_hint
); break;
3585 case AST_SUB
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) - children
[1]->asReal(sign_hint
); break;
3586 case AST_MUL
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) * children
[1]->asReal(sign_hint
); break;
3587 case AST_DIV
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) / children
[1]->asReal(sign_hint
); break;
3588 case AST_MOD
: newNode
->realvalue
= fmod(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
)); break;
3589 default: log_abort();
3593 if (0) { case AST_SELFSZ
: const_func
= RTLIL::const_pos
; }
3594 if (0) { case AST_POS
: const_func
= RTLIL::const_pos
; }
3595 if (0) { case AST_NEG
: const_func
= RTLIL::const_neg
; }
3596 if (children
[0]->type
== AST_CONSTANT
) {
3597 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
3598 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3600 if (children
[0]->isConst()) {
3601 newNode
= new AstNode(AST_REALVALUE
);
3602 if (type
== AST_NEG
)
3603 newNode
->realvalue
= -children
[0]->asReal(sign_hint
);
3605 newNode
->realvalue
= +children
[0]->asReal(sign_hint
);
3609 if (children
[0]->isConst())
3611 bool found_sure_true
= false;
3612 bool found_maybe_true
= false;
3614 if (children
[0]->type
== AST_CONSTANT
)
3615 for (auto &bit
: children
[0]->bits
) {
3616 if (bit
== RTLIL::State::S1
)
3617 found_sure_true
= true;
3618 if (bit
> RTLIL::State::S1
)
3619 found_maybe_true
= true;
3622 found_sure_true
= children
[0]->asReal(sign_hint
) != 0;
3624 AstNode
*choice
= NULL
, *not_choice
= NULL
;
3625 if (found_sure_true
)
3626 choice
= children
[1], not_choice
= children
[2];
3627 else if (!found_maybe_true
)
3628 choice
= children
[2], not_choice
= children
[1];
3630 if (choice
!= NULL
) {
3631 if (choice
->type
== AST_CONSTANT
) {
3632 int other_width_hint
= width_hint
;
3633 bool other_sign_hint
= sign_hint
, other_real
= false;
3634 not_choice
->detectSignWidth(other_width_hint
, other_sign_hint
, &other_real
);
3636 newNode
= new AstNode(AST_REALVALUE
);
3637 choice
->detectSignWidth(width_hint
, sign_hint
);
3638 newNode
->realvalue
= choice
->asReal(sign_hint
);
3640 RTLIL::Const y
= choice
->bitsAsConst(width_hint
, sign_hint
);
3641 if (choice
->is_string
&& y
.bits
.size() % 8 == 0 && sign_hint
== false)
3642 newNode
= mkconst_str(y
.bits
);
3644 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3647 if (choice
->isConst()) {
3648 newNode
= choice
->clone();
3650 } else if (children
[1]->type
== AST_CONSTANT
&& children
[2]->type
== AST_CONSTANT
) {
3651 RTLIL::Const a
= children
[1]->bitsAsConst(width_hint
, sign_hint
);
3652 RTLIL::Const b
= children
[2]->bitsAsConst(width_hint
, sign_hint
);
3653 log_assert(a
.bits
.size() == b
.bits
.size());
3654 for (size_t i
= 0; i
< a
.bits
.size(); i
++)
3655 if (a
.bits
[i
] != b
.bits
[i
])
3656 a
.bits
[i
] = RTLIL::State::Sx
;
3657 newNode
= mkconst_bits(a
.bits
, sign_hint
);
3658 } else if (children
[1]->isConst() && children
[2]->isConst()) {
3659 newNode
= new AstNode(AST_REALVALUE
);
3660 if (children
[1]->asReal(sign_hint
) == children
[2]->asReal(sign_hint
))
3661 newNode
->realvalue
= children
[1]->asReal(sign_hint
);
3663 // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
3664 // the data type in question should be returned if the ?: is ambiguous. The
3665 // value in Table 7-1 for the 'real' type is 0.0.
3666 newNode
->realvalue
= 0.0;
3671 if (children
.at(0)->type
== AST_CONSTANT
&& children
.at(1)->type
== AST_CONSTANT
) {
3672 int width
= children
[0]->bitsAsConst().as_int();
3673 RTLIL::Const val
= children
[1]->bitsAsConst(width
);
3674 newNode
= mkconst_bits(val
.bits
, children
[1]->is_signed
);
3678 string_op
= !children
.empty();
3679 for (auto it
= children
.begin(); it
!= children
.end(); it
++) {
3680 if ((*it
)->type
!= AST_CONSTANT
)
3682 if (!(*it
)->is_string
)
3684 tmp_bits
.insert(tmp_bits
.end(), (*it
)->bits
.begin(), (*it
)->bits
.end());
3686 newNode
= string_op
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
3689 if (children
.at(0)->type
!= AST_CONSTANT
|| children
.at(1)->type
!= AST_CONSTANT
)
3691 for (int i
= 0; i
< children
[0]->bitsAsConst().as_int(); i
++)
3692 tmp_bits
.insert(tmp_bits
.end(), children
.at(1)->bits
.begin(), children
.at(1)->bits
.end());
3693 newNode
= children
.at(1)->is_string
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
3701 // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
3704 // fprintf(stderr, "----\n");
3705 // dumpAst(stderr, "- ");
3706 // newNode->dumpAst(stderr, "+ ");
3707 log_assert(newNode
!= NULL
);
3708 newNode
->filename
= filename
;
3709 newNode
->location
= location
;
3710 newNode
->cloneInto(this);
3712 did_something
= true;
3718 recursion_counter
--;
3719 return did_something
;
3722 void AstNode::replace_result_wire_name_in_function(const std::string
&from
, const std::string
&to
)
3724 for (AstNode
*child
: children
)
3725 child
->replace_result_wire_name_in_function(from
, to
);
3726 if (str
== from
&& type
!= AST_FCALL
&& type
!= AST_TCALL
)
3730 // replace a readmem[bh] TCALL ast node with a block of memory assignments
3731 AstNode
*AstNode::readmem(bool is_readmemh
, std::string mem_filename
, AstNode
*memory
, int start_addr
, int finish_addr
, bool unconditional_init
)
3733 int mem_width
, mem_size
, addr_bits
;
3734 memory
->meminfo(mem_width
, mem_size
, addr_bits
);
3736 AstNode
*block
= new AstNode(AST_BLOCK
);
3738 AstNode
*meminit
= nullptr;
3739 int next_meminit_cursor
=0;
3740 vector
<State
> meminit_bits
;
3744 f
.open(mem_filename
.c_str());
3751 std::string path
= filename
.substr(0, filename
.find_last_of(slash
)+1);
3752 f
.open(path
+ mem_filename
.c_str());
3753 yosys_input_files
.insert(path
+ mem_filename
);
3755 yosys_input_files
.insert(mem_filename
);
3757 if (f
.fail() || GetSize(mem_filename
) == 0)
3758 log_file_error(filename
, location
.first_line
, "Can not open file `%s` for %s.\n", mem_filename
.c_str(), str
.c_str());
3760 log_assert(GetSize(memory
->children
) == 2 && memory
->children
[1]->type
== AST_RANGE
&& memory
->children
[1]->range_valid
);
3761 int range_left
= memory
->children
[1]->range_left
, range_right
= memory
->children
[1]->range_right
;
3762 int range_min
= min(range_left
, range_right
), range_max
= max(range_left
, range_right
);
3765 start_addr
= range_min
;
3767 if (finish_addr
< 0)
3768 finish_addr
= range_max
+ 1;
3770 bool in_comment
= false;
3771 int increment
= start_addr
<= finish_addr
? +1 : -1;
3772 int cursor
= start_addr
;
3776 std::string line
, token
;
3777 std::getline(f
, line
);
3779 for (int i
= 0; i
< GetSize(line
); i
++) {
3780 if (in_comment
&& line
.compare(i
, 2, "*/") == 0) {
3786 if (!in_comment
&& line
.compare(i
, 2, "/*") == 0)
3794 token
= next_token(line
, " \t\r\n");
3795 if (token
.empty() || token
.compare(0, 2, "//") == 0)
3798 if (token
[0] == '@') {
3799 token
= token
.substr(1);
3800 const char *nptr
= token
.c_str();
3802 cursor
= strtol(nptr
, &endptr
, 16);
3803 if (!*nptr
|| *endptr
)
3804 log_file_error(filename
, location
.first_line
, "Can not parse address `%s` for %s.\n", nptr
, str
.c_str());
3808 AstNode
*value
= VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width
, is_readmemh
? 'h' : 'b') + token
);
3810 if (unconditional_init
)
3812 if (meminit
== nullptr || cursor
!= next_meminit_cursor
)
3814 if (meminit
!= nullptr) {
3815 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
3816 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
3819 meminit
= new AstNode(AST_MEMINIT
);
3820 meminit
->children
.push_back(AstNode::mkconst_int(cursor
, false));
3821 meminit
->children
.push_back(nullptr);
3822 meminit
->children
.push_back(nullptr);
3823 meminit
->str
= memory
->str
;
3824 meminit
->id2ast
= memory
;
3825 meminit_bits
.clear();
3828 current_ast_mod
->children
.push_back(meminit
);
3829 next_meminit_cursor
= cursor
;
3833 next_meminit_cursor
++;
3834 meminit_bits
.insert(meminit_bits
.end(), value
->bits
.begin(), value
->bits
.end());
3839 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
, false))), value
));
3840 block
->children
.back()->children
[0]->str
= memory
->str
;
3841 block
->children
.back()->children
[0]->id2ast
= memory
;
3842 block
->children
.back()->children
[0]->was_checked
= true;
3845 cursor
+= increment
;
3846 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
3850 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
3854 if (meminit
!= nullptr) {
3855 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
3856 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
3862 // annotate the names of all wires and other named objects in a generate block
3863 void AstNode::expand_genblock(std::string index_var
, std::string prefix
, std::map
<std::string
, std::string
> &name_map
, bool original_scope
)
3865 // `original_scope` defaults to false, and is used to prevent the premature
3866 // prefixing of items in named sub-blocks
3868 if (!index_var
.empty() && type
== AST_IDENTIFIER
&& str
== index_var
) {
3869 if (children
.empty()) {
3870 current_scope
[index_var
]->children
[0]->cloneInto(this);
3872 AstNode
*p
= new AstNode(AST_LOCALPARAM
, current_scope
[index_var
]->children
[0]->clone());
3873 p
->str
= stringf("$genval$%d", autoidx
++);
3874 current_ast_mod
->children
.push_back(p
);
3880 if (type
== AST_IDENTIFIER
|| type
== AST_FCALL
|| type
== AST_TCALL
|| type
== AST_WIRETYPE
) {
3881 if (name_map
.count(str
) > 0) {
3882 str
= name_map
[str
];
3884 // remap the prefix of this ident if it is a local generate scope
3885 size_t pos
= str
.rfind('.');
3886 if (pos
!= std::string::npos
) {
3887 std::string existing_prefix
= str
.substr(0, pos
);
3888 if (name_map
.count(existing_prefix
) > 0) {
3889 str
= name_map
[existing_prefix
] + str
.substr(pos
);
3895 std::map
<std::string
, std::string
> backup_name_map
;
3897 auto prefix_node
= [&](AstNode
* child
) {
3898 if (backup_name_map
.size() == 0)
3899 backup_name_map
= name_map
;
3901 // if within a nested scope
3902 if (!original_scope
) {
3903 // this declaration shadows anything in the parent scope(s)
3904 name_map
[child
->str
] = child
->str
;
3908 std::string new_name
= prefix
[0] == '\\' ? prefix
.substr(1) : prefix
;
3909 size_t pos
= child
->str
.rfind('.');
3910 if (pos
== std::string::npos
)
3911 pos
= child
->str
[0] == '\\' && prefix
[0] == '\\' ? 1 : 0;
3914 new_name
= child
->str
.substr(0, pos
) + new_name
+ child
->str
.substr(pos
);
3915 if (new_name
[0] != '$' && new_name
[0] != '\\')
3916 new_name
= prefix
[0] + new_name
;
3918 name_map
[child
->str
] = new_name
;
3919 if (child
->type
== AST_FUNCTION
)
3920 child
->replace_result_wire_name_in_function(child
->str
, new_name
);
3922 child
->str
= new_name
;
3923 current_scope
[new_name
] = child
;
3926 for (size_t i
= 0; i
< children
.size(); i
++) {
3927 AstNode
*child
= children
[i
];
3929 switch (child
->type
) {
3933 case AST_LOCALPARAM
:
3945 if (!child
->str
.empty())
3950 current_scope
[child
->str
] = child
;
3951 for (auto enode
: child
->children
){
3952 log_assert(enode
->type
== AST_ENUM_ITEM
);
3962 for (size_t i
= 0; i
< children
.size(); i
++) {
3963 AstNode
*child
= children
[i
];
3964 // AST_PREFIX member names should not be prefixed; a nested AST_PREFIX
3965 // still needs to recursed-into
3966 if (type
== AST_PREFIX
&& i
== 1 && child
->type
== AST_IDENTIFIER
)
3968 // functions/tasks may reference wires, constants, etc. in this scope
3969 if (child
->type
== AST_FUNCTION
|| child
->type
== AST_TASK
)
3970 child
->expand_genblock(index_var
, prefix
, name_map
, false);
3971 // continue prefixing if this child block is anonymous
3972 else if (child
->type
== AST_GENBLOCK
|| child
->type
== AST_BLOCK
)
3973 child
->expand_genblock(index_var
, prefix
, name_map
, original_scope
&& child
->str
.empty());
3975 child
->expand_genblock(index_var
, prefix
, name_map
, original_scope
);
3979 if (backup_name_map
.size() > 0)
3980 name_map
.swap(backup_name_map
);
3983 // rename stuff (used when tasks of functions are instantiated)
3984 void AstNode::replace_ids(const std::string
&prefix
, const std::map
<std::string
, std::string
> &rules
)
3986 if (type
== AST_BLOCK
)
3988 std::map
<std::string
, std::string
> new_rules
= rules
;
3989 std::string new_prefix
= prefix
+ str
;
3991 for (auto child
: children
)
3992 if (child
->type
== AST_WIRE
) {
3993 new_rules
[child
->str
] = new_prefix
+ child
->str
;
3994 child
->str
= new_prefix
+ child
->str
;
3997 for (auto child
: children
)
3998 if (child
->type
!= AST_WIRE
)
3999 child
->replace_ids(new_prefix
, new_rules
);
4003 if (type
== AST_IDENTIFIER
&& rules
.count(str
) > 0)
4004 str
= rules
.at(str
);
4005 for (auto child
: children
)
4006 child
->replace_ids(prefix
, rules
);
4010 // helper function for mem2reg_as_needed_pass1
4011 static void mark_memories_assign_lhs_complex(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
4012 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, AstNode
*that
)
4014 for (auto &child
: that
->children
)
4015 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, child
);
4017 if (that
->type
== AST_IDENTIFIER
&& that
->id2ast
&& that
->id2ast
->type
== AST_MEMORY
) {
4018 AstNode
*mem
= that
->id2ast
;
4019 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_CMPLX_LHS
))
4020 mem2reg_places
[mem
].insert(stringf("%s:%d", that
->filename
.c_str(), that
->location
.first_line
));
4021 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CMPLX_LHS
;
4025 // find memories that should be replaced by registers
4026 void AstNode::mem2reg_as_needed_pass1(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
4027 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, dict
<AstNode
*, uint32_t> &proc_flags
, uint32_t &flags
)
4029 uint32_t children_flags
= 0;
4030 int lhs_children_counter
= 0;
4032 if (type
== AST_TYPEDEF
)
4033 return; // don't touch content of typedefs
4035 if (type
== AST_ASSIGN
|| type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
)
4037 // mark all memories that are used in a complex expression on the left side of an assignment
4038 for (auto &lhs_child
: children
[0]->children
)
4039 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, lhs_child
);
4041 if (children
[0]->type
== AST_IDENTIFIER
&& children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
)
4043 AstNode
*mem
= children
[0]->id2ast
;
4045 // activate mem2reg if this is assigned in an async proc
4046 if (flags
& AstNode::MEM2REG_FL_ASYNC
) {
4047 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ASYNC
))
4048 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
4049 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ASYNC
;
4052 // remember if this is assigned blocking (=)
4053 if (type
== AST_ASSIGN_EQ
) {
4054 if (!(proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
))
4055 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
4056 proc_flags
[mem
] |= AstNode::MEM2REG_FL_EQ1
;
4059 // for proper (non-init) writes: remember if this is a constant index or not
4060 if ((flags
& MEM2REG_FL_INIT
) == 0) {
4061 if (children
[0]->children
.size() && children
[0]->children
[0]->type
== AST_RANGE
&& children
[0]->children
[0]->children
.size()) {
4062 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
)
4063 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CONST_LHS
;
4065 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_VAR_LHS
;
4069 // remember where this is
4070 if (flags
& MEM2REG_FL_INIT
) {
4071 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_INIT
))
4072 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
4073 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_INIT
;
4075 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ELSE
))
4076 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
4077 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ELSE
;
4081 lhs_children_counter
= 1;
4084 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
)
4086 AstNode
*mem
= id2ast
;
4088 // flag if used after blocking assignment (in same proc)
4089 if ((proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
) && !(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_EQ2
)) {
4090 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
4091 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_EQ2
;
4095 // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg' or 'logic'
4096 if (type
== AST_MEMORY
&& (get_bool_attribute(ID::mem2reg
) || (flags
& AstNode::MEM2REG_FL_ALL
) || !(is_reg
|| is_logic
)))
4097 mem2reg_candidates
[this] |= AstNode::MEM2REG_FL_FORCED
;
4099 if (type
== AST_MODULE
&& get_bool_attribute(ID::mem2reg
))
4100 children_flags
|= AstNode::MEM2REG_FL_ALL
;
4102 dict
<AstNode
*, uint32_t> *proc_flags_p
= NULL
;
4104 if (type
== AST_ALWAYS
) {
4105 int count_edge_events
= 0;
4106 for (auto child
: children
)
4107 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
4108 count_edge_events
++;
4109 if (count_edge_events
!= 1)
4110 children_flags
|= AstNode::MEM2REG_FL_ASYNC
;
4111 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
4114 if (type
== AST_INITIAL
) {
4115 children_flags
|= AstNode::MEM2REG_FL_INIT
;
4116 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
4119 uint32_t backup_flags
= flags
;
4120 flags
|= children_flags
;
4121 log_assert((flags
& ~0x000000ff) == 0);
4123 for (auto child
: children
)
4125 if (lhs_children_counter
> 0) {
4126 lhs_children_counter
--;
4127 if (child
->children
.size() && child
->children
[0]->type
== AST_RANGE
&& child
->children
[0]->children
.size()) {
4128 for (auto c
: child
->children
[0]->children
) {
4130 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
4132 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
4137 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
4139 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
4142 flags
&= ~children_flags
| backup_flags
;
4146 for (auto it
: *proc_flags_p
)
4147 log_assert((it
.second
& ~0xff000000) == 0);
4149 delete proc_flags_p
;
4153 bool AstNode::mem2reg_check(pool
<AstNode
*> &mem2reg_set
)
4155 if (type
!= AST_IDENTIFIER
|| !id2ast
|| !mem2reg_set
.count(id2ast
))
4158 if (children
.empty() || children
[0]->type
!= AST_RANGE
|| GetSize(children
[0]->children
) != 1)
4159 log_file_error(filename
, location
.first_line
, "Invalid array access.\n");
4164 void AstNode::mem2reg_remove(pool
<AstNode
*> &mem2reg_set
, vector
<AstNode
*> &delnodes
)
4166 log_assert(mem2reg_set
.count(this) == 0);
4168 if (mem2reg_set
.count(id2ast
))
4171 for (size_t i
= 0; i
< children
.size(); i
++) {
4172 if (mem2reg_set
.count(children
[i
]) > 0) {
4173 delnodes
.push_back(children
[i
]);
4174 children
.erase(children
.begin() + (i
--));
4176 children
[i
]->mem2reg_remove(mem2reg_set
, delnodes
);
4181 // actually replace memories with registers
4182 bool AstNode::mem2reg_as_needed_pass2(pool
<AstNode
*> &mem2reg_set
, AstNode
*mod
, AstNode
*block
, AstNode
*&async_block
)
4184 bool did_something
= false;
4186 if (type
== AST_BLOCK
)
4189 if (type
== AST_FUNCTION
|| type
== AST_TASK
)
4192 if (type
== AST_TYPEDEF
)
4195 if (type
== AST_MEMINIT
&& id2ast
&& mem2reg_set
.count(id2ast
))
4197 log_assert(children
[0]->type
== AST_CONSTANT
);
4198 log_assert(children
[1]->type
== AST_CONSTANT
);
4199 log_assert(children
[2]->type
== AST_CONSTANT
);
4201 int cursor
= children
[0]->asInt(false);
4202 Const data
= children
[1]->bitsAsConst();
4203 int length
= children
[2]->asInt(false);
4207 AstNode
*block
= new AstNode(AST_INITIAL
, new AstNode(AST_BLOCK
));
4208 mod
->children
.push_back(block
);
4209 block
= block
->children
[0];
4211 int wordsz
= GetSize(data
) / length
;
4213 for (int i
= 0; i
< length
; i
++) {
4214 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+i
, false))), mkconst_bits(data
.extract(i
*wordsz
, wordsz
).bits
, false)));
4215 block
->children
.back()->children
[0]->str
= str
;
4216 block
->children
.back()->children
[0]->id2ast
= id2ast
;
4217 block
->children
.back()->children
[0]->was_checked
= true;
4221 AstNode
*newNode
= new AstNode(AST_NONE
);
4222 newNode
->cloneInto(this);
4225 did_something
= true;
4228 if (type
== AST_ASSIGN
&& block
== NULL
&& children
[0]->mem2reg_check(mem2reg_set
))
4230 if (async_block
== NULL
) {
4231 async_block
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
4232 mod
->children
.push_back(async_block
);
4235 AstNode
*newNode
= clone();
4236 newNode
->type
= AST_ASSIGN_EQ
;
4237 newNode
->children
[0]->was_checked
= true;
4238 async_block
->children
[0]->children
.push_back(newNode
);
4240 newNode
= new AstNode(AST_NONE
);
4241 newNode
->cloneInto(this);
4244 did_something
= true;
4247 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->mem2reg_check(mem2reg_set
) &&
4248 children
[0]->children
[0]->children
[0]->type
!= AST_CONSTANT
)
4250 std::stringstream sstr
;
4251 sstr
<< "$mem2reg_wr$" << children
[0]->str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
4252 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
4254 int mem_width
, mem_size
, addr_bits
;
4255 bool mem_signed
= children
[0]->id2ast
->is_signed
;
4256 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
4258 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
4259 wire_addr
->str
= id_addr
;
4260 wire_addr
->is_reg
= true;
4261 wire_addr
->was_checked
= true;
4262 wire_addr
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
4263 mod
->children
.push_back(wire_addr
);
4264 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
4266 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
4267 wire_data
->str
= id_data
;
4268 wire_data
->is_reg
= true;
4269 wire_data
->was_checked
= true;
4270 wire_data
->is_signed
= mem_signed
;
4271 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
4272 mod
->children
.push_back(wire_data
);
4273 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
4275 log_assert(block
!= NULL
);
4276 size_t assign_idx
= 0;
4277 while (assign_idx
< block
->children
.size() && block
->children
[assign_idx
] != this)
4279 log_assert(assign_idx
< block
->children
.size());
4281 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
4282 assign_addr
->children
[0]->str
= id_addr
;
4283 assign_addr
->children
[0]->was_checked
= true;
4284 block
->children
.insert(block
->children
.begin()+assign_idx
+1, assign_addr
);
4286 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
4287 case_node
->children
[0]->str
= id_addr
;
4288 for (int i
= 0; i
< mem_size
; i
++) {
4289 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->children
[0]->integer
) != i
)
4291 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
4292 AstNode
*assign_reg
= new AstNode(type
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
4293 if (children
[0]->children
.size() == 2)
4294 assign_reg
->children
[0]->children
.push_back(children
[0]->children
[1]->clone());
4295 assign_reg
->children
[0]->str
= stringf("%s[%d]", children
[0]->str
.c_str(), i
);
4296 assign_reg
->children
[1]->str
= id_data
;
4297 cond_node
->children
[1]->children
.push_back(assign_reg
);
4298 case_node
->children
.push_back(cond_node
);
4300 block
->children
.insert(block
->children
.begin()+assign_idx
+2, case_node
);
4302 children
[0]->delete_children();
4303 children
[0]->range_valid
= false;
4304 children
[0]->id2ast
= NULL
;
4305 children
[0]->str
= id_data
;
4306 type
= AST_ASSIGN_EQ
;
4307 children
[0]->was_checked
= true;
4309 did_something
= true;
4312 if (mem2reg_check(mem2reg_set
))
4314 AstNode
*bit_part_sel
= NULL
;
4315 if (children
.size() == 2)
4316 bit_part_sel
= children
[1]->clone();
4318 if (children
[0]->children
[0]->type
== AST_CONSTANT
)
4320 int id
= children
[0]->children
[0]->integer
;
4321 str
= stringf("%s[%d]", str
.c_str(), id
);
4324 range_valid
= false;
4329 std::stringstream sstr
;
4330 sstr
<< "$mem2reg_rd$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
4331 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
4333 int mem_width
, mem_size
, addr_bits
;
4334 bool mem_signed
= id2ast
->is_signed
;
4335 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
4337 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
4338 wire_addr
->str
= id_addr
;
4339 wire_addr
->is_reg
= true;
4340 wire_addr
->was_checked
= true;
4342 wire_addr
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
4343 mod
->children
.push_back(wire_addr
);
4344 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
4346 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
4347 wire_data
->str
= id_data
;
4348 wire_data
->is_reg
= true;
4349 wire_data
->was_checked
= true;
4350 wire_data
->is_signed
= mem_signed
;
4352 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
4353 mod
->children
.push_back(wire_data
);
4354 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
4356 AstNode
*assign_addr
= new AstNode(block
? AST_ASSIGN_EQ
: AST_ASSIGN
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->clone());
4357 assign_addr
->children
[0]->str
= id_addr
;
4358 assign_addr
->children
[0]->was_checked
= true;
4360 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
4361 case_node
->children
[0]->str
= id_addr
;
4363 for (int i
= 0; i
< mem_size
; i
++) {
4364 if (children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->integer
) != i
)
4366 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
4367 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
4368 assign_reg
->children
[0]->str
= id_data
;
4369 assign_reg
->children
[0]->was_checked
= true;
4370 assign_reg
->children
[1]->str
= stringf("%s[%d]", str
.c_str(), i
);
4371 cond_node
->children
[1]->children
.push_back(assign_reg
);
4372 case_node
->children
.push_back(cond_node
);
4375 std::vector
<RTLIL::State
> x_bits
;
4376 for (int i
= 0; i
< mem_width
; i
++)
4377 x_bits
.push_back(RTLIL::State::Sx
);
4379 AstNode
*cond_node
= new AstNode(AST_COND
, new AstNode(AST_DEFAULT
), new AstNode(AST_BLOCK
));
4380 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), AstNode::mkconst_bits(x_bits
, false));
4381 assign_reg
->children
[0]->str
= id_data
;
4382 assign_reg
->children
[0]->was_checked
= true;
4383 cond_node
->children
[1]->children
.push_back(assign_reg
);
4384 case_node
->children
.push_back(cond_node
);
4388 size_t assign_idx
= 0;
4389 while (assign_idx
< block
->children
.size() && !block
->children
[assign_idx
]->contains(this))
4391 log_assert(assign_idx
< block
->children
.size());
4392 block
->children
.insert(block
->children
.begin()+assign_idx
, case_node
);
4393 block
->children
.insert(block
->children
.begin()+assign_idx
, assign_addr
);
4397 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
4398 proc
->children
[0]->children
.push_back(case_node
);
4399 mod
->children
.push_back(proc
);
4400 mod
->children
.push_back(assign_addr
);
4404 range_valid
= false;
4410 children
.push_back(bit_part_sel
);
4412 did_something
= true;
4415 log_assert(id2ast
== NULL
|| mem2reg_set
.count(id2ast
) == 0);
4417 auto children_list
= children
;
4418 for (size_t i
= 0; i
< children_list
.size(); i
++)
4419 if (children_list
[i
]->mem2reg_as_needed_pass2(mem2reg_set
, mod
, block
, async_block
))
4420 did_something
= true;
4422 return did_something
;
4425 // calculate memory dimensions
4426 void AstNode::meminfo(int &mem_width
, int &mem_size
, int &addr_bits
)
4428 log_assert(type
== AST_MEMORY
);
4430 mem_width
= children
[0]->range_left
- children
[0]->range_right
+ 1;
4431 mem_size
= children
[1]->range_left
- children
[1]->range_right
;
4435 mem_size
+= min(children
[1]->range_left
, children
[1]->range_right
) + 1;
4438 while ((1 << addr_bits
) < mem_size
)
4442 bool AstNode::detect_latch(const std::string
&var
)
4447 for (auto &c
: children
)
4457 if (!c
->detect_latch(var
))
4466 for (auto &c
: children
)
4467 if (!c
->detect_latch(var
))
4473 for (auto &c
: children
) {
4474 if (c
->type
== AST_COND
) {
4475 if (c
->children
.at(1)->detect_latch(var
))
4479 if (c
->type
== AST_DEFAULT
) {
4480 if (c
->children
.at(0)->detect_latch(var
))
4489 if (children
.at(0)->type
== AST_IDENTIFIER
&&
4490 children
.at(0)->children
.empty() && children
.at(0)->str
== var
)
4498 bool AstNode::has_const_only_constructs(bool &recommend_const_eval
)
4500 std::set
<std::string
> visited
;
4501 return has_const_only_constructs(visited
, recommend_const_eval
);
4504 bool AstNode::has_const_only_constructs(std::set
<std::string
>& visited
, bool &recommend_const_eval
)
4506 if (type
== AST_FUNCTION
|| type
== AST_TASK
)
4508 if (visited
.count(str
))
4510 recommend_const_eval
= true;
4513 visited
.insert(str
);
4516 if (type
== AST_FOR
)
4517 recommend_const_eval
= true;
4518 if (type
== AST_WHILE
|| type
== AST_REPEAT
)
4520 if (type
== AST_FCALL
&& current_scope
.count(str
))
4521 if (current_scope
[str
]->has_const_only_constructs(visited
, recommend_const_eval
))
4523 for (auto child
: children
)
4524 if (child
->AstNode::has_const_only_constructs(visited
, recommend_const_eval
))
4529 bool AstNode::is_simple_const_expr()
4531 if (type
== AST_IDENTIFIER
)
4533 for (auto child
: children
)
4534 if (!child
->is_simple_const_expr())
4539 // helper function for AstNode::eval_const_function()
4540 void AstNode::replace_variables(std::map
<std::string
, AstNode::varinfo_t
> &variables
, AstNode
*fcall
)
4542 if (type
== AST_IDENTIFIER
&& variables
.count(str
)) {
4543 int offset
= variables
.at(str
).offset
, width
= variables
.at(str
).val
.bits
.size();
4544 if (!children
.empty()) {
4545 if (children
.size() != 1 || children
.at(0)->type
!= AST_RANGE
)
4546 log_file_error(filename
, location
.first_line
, "Memory access in constant function is not supported\n%s:%d.%d-%d.%d: ...called from here.\n",
4547 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4548 children
.at(0)->replace_variables(variables
, fcall
);
4549 while (simplify(true, false, false, 1, -1, false, true)) { }
4550 if (!children
.at(0)->range_valid
)
4551 log_file_error(filename
, location
.first_line
, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
4552 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4553 offset
= min(children
.at(0)->range_left
, children
.at(0)->range_right
);
4554 width
= min(std::abs(children
.at(0)->range_left
- children
.at(0)->range_right
) + 1, width
);
4556 offset
-= variables
.at(str
).offset
;
4557 std::vector
<RTLIL::State
> &var_bits
= variables
.at(str
).val
.bits
;
4558 std::vector
<RTLIL::State
> new_bits(var_bits
.begin() + offset
, var_bits
.begin() + offset
+ width
);
4559 AstNode
*newNode
= mkconst_bits(new_bits
, variables
.at(str
).is_signed
);
4560 newNode
->cloneInto(this);
4565 for (auto &child
: children
)
4566 child
->replace_variables(variables
, fcall
);
4569 // evaluate functions with all-const arguments
4570 AstNode
*AstNode::eval_const_function(AstNode
*fcall
)
4572 std::map
<std::string
, AstNode
*> backup_scope
;
4573 std::map
<std::string
, AstNode::varinfo_t
> variables
;
4574 AstNode
*block
= new AstNode(AST_BLOCK
);
4577 for (auto child
: children
)
4579 block
->children
.push_back(child
->clone());
4582 while (!block
->children
.empty())
4584 AstNode
*stmt
= block
->children
.front();
4587 log("-----------------------------------\n");
4588 for (auto &it
: variables
)
4589 log("%20s %40s\n", it
.first
.c_str(), log_signal(it
.second
.val
));
4590 stmt
->dumpAst(NULL
, "stmt> ");
4593 if (stmt
->type
== AST_WIRE
)
4595 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
4596 if (!stmt
->range_valid
)
4597 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Can't determine size of variable %s\n%s:%d.%d-%d.%d: ... called from here.\n",
4598 stmt
->str
.c_str(), fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4599 variables
[stmt
->str
].val
= RTLIL::Const(RTLIL::State::Sx
, abs(stmt
->range_left
- stmt
->range_right
)+1);
4600 variables
[stmt
->str
].offset
= min(stmt
->range_left
, stmt
->range_right
);
4601 variables
[stmt
->str
].is_signed
= stmt
->is_signed
;
4602 if (stmt
->is_input
&& argidx
< fcall
->children
.size()) {
4603 int width
= variables
[stmt
->str
].val
.bits
.size();
4604 auto* arg_node
= fcall
->children
.at(argidx
++);
4605 if (arg_node
->type
== AST_CONSTANT
) {
4606 variables
[stmt
->str
].val
= arg_node
->bitsAsConst(width
);
4608 log_assert(arg_node
->type
== AST_REALVALUE
);
4609 variables
[stmt
->str
].val
= arg_node
->realAsConst(width
);
4612 if (!backup_scope
.count(stmt
->str
))
4613 backup_scope
[stmt
->str
] = current_scope
[stmt
->str
];
4614 current_scope
[stmt
->str
] = stmt
;
4616 block
->children
.erase(block
->children
.begin());
4620 log_assert(variables
.count(str
) != 0);
4622 if (stmt
->type
== AST_LOCALPARAM
)
4624 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
4626 if (!backup_scope
.count(stmt
->str
))
4627 backup_scope
[stmt
->str
] = current_scope
[stmt
->str
];
4628 current_scope
[stmt
->str
] = stmt
;
4630 block
->children
.erase(block
->children
.begin());
4634 if (stmt
->type
== AST_ASSIGN_EQ
)
4636 if (stmt
->children
.at(0)->type
== AST_IDENTIFIER
&& stmt
->children
.at(0)->children
.size() != 0 &&
4637 stmt
->children
.at(0)->children
.at(0)->type
== AST_RANGE
)
4638 stmt
->children
.at(0)->children
.at(0)->replace_variables(variables
, fcall
);
4639 stmt
->children
.at(1)->replace_variables(variables
, fcall
);
4640 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
4642 if (stmt
->type
!= AST_ASSIGN_EQ
)
4645 if (stmt
->children
.at(1)->type
!= AST_CONSTANT
)
4646 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here. X\n",
4647 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4649 if (stmt
->children
.at(0)->type
!= AST_IDENTIFIER
)
4650 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Unsupported composite left hand side in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4651 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4653 if (!variables
.count(stmt
->children
.at(0)->str
))
4654 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Assignment to non-local variable in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4655 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4657 if (stmt
->children
.at(0)->children
.empty()) {
4658 variables
[stmt
->children
.at(0)->str
].val
= stmt
->children
.at(1)->bitsAsConst(variables
[stmt
->children
.at(0)->str
].val
.bits
.size());
4660 AstNode
*range
= stmt
->children
.at(0)->children
.at(0);
4661 if (!range
->range_valid
)
4662 log_file_error(range
->filename
, range
->location
.first_line
, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
4663 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4664 int offset
= min(range
->range_left
, range
->range_right
);
4665 int width
= std::abs(range
->range_left
- range
->range_right
) + 1;
4666 varinfo_t
&v
= variables
[stmt
->children
.at(0)->str
];
4667 RTLIL::Const r
= stmt
->children
.at(1)->bitsAsConst(v
.val
.bits
.size());
4668 for (int i
= 0; i
< width
; i
++)
4669 v
.val
.bits
.at(i
+offset
-v
.offset
) = r
.bits
.at(i
);
4672 delete block
->children
.front();
4673 block
->children
.erase(block
->children
.begin());
4677 if (stmt
->type
== AST_FOR
)
4679 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(0));
4680 stmt
->children
.at(3)->children
.push_back(stmt
->children
.at(2));
4681 stmt
->children
.erase(stmt
->children
.begin() + 2);
4682 stmt
->children
.erase(stmt
->children
.begin());
4683 stmt
->type
= AST_WHILE
;
4687 if (stmt
->type
== AST_WHILE
)
4689 AstNode
*cond
= stmt
->children
.at(0)->clone();
4690 cond
->replace_variables(variables
, fcall
);
4691 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
4693 if (cond
->type
!= AST_CONSTANT
)
4694 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4695 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4697 if (cond
->asBool()) {
4698 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
4700 delete block
->children
.front();
4701 block
->children
.erase(block
->children
.begin());
4708 if (stmt
->type
== AST_REPEAT
)
4710 AstNode
*num
= stmt
->children
.at(0)->clone();
4711 num
->replace_variables(variables
, fcall
);
4712 while (num
->simplify(true, false, false, 1, -1, false, true)) { }
4714 if (num
->type
!= AST_CONSTANT
)
4715 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4716 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4718 block
->children
.erase(block
->children
.begin());
4719 for (int i
= 0; i
< num
->bitsAsConst().as_int(); i
++)
4720 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
4727 if (stmt
->type
== AST_CASE
)
4729 AstNode
*expr
= stmt
->children
.at(0)->clone();
4730 expr
->replace_variables(variables
, fcall
);
4731 while (expr
->simplify(true, false, false, 1, -1, false, true)) { }
4733 AstNode
*sel_case
= NULL
;
4734 for (size_t i
= 1; i
< stmt
->children
.size(); i
++)
4736 bool found_match
= false;
4737 log_assert(stmt
->children
.at(i
)->type
== AST_COND
|| stmt
->children
.at(i
)->type
== AST_CONDX
|| stmt
->children
.at(i
)->type
== AST_CONDZ
);
4739 if (stmt
->children
.at(i
)->children
.front()->type
== AST_DEFAULT
) {
4740 sel_case
= stmt
->children
.at(i
)->children
.back();
4744 for (size_t j
= 0; j
+1 < stmt
->children
.at(i
)->children
.size() && !found_match
; j
++)
4746 AstNode
*cond
= stmt
->children
.at(i
)->children
.at(j
)->clone();
4747 cond
->replace_variables(variables
, fcall
);
4749 cond
= new AstNode(AST_EQ
, expr
->clone(), cond
);
4750 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
4752 if (cond
->type
!= AST_CONSTANT
)
4753 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4754 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4756 found_match
= cond
->asBool();
4761 sel_case
= stmt
->children
.at(i
)->children
.back();
4766 block
->children
.erase(block
->children
.begin());
4768 block
->children
.insert(block
->children
.begin(), sel_case
->clone());
4774 if (stmt
->type
== AST_BLOCK
)
4776 block
->children
.erase(block
->children
.begin());
4777 block
->children
.insert(block
->children
.begin(), stmt
->children
.begin(), stmt
->children
.end());
4778 stmt
->children
.clear();
4783 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Unsupported language construct in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4784 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4790 for (auto &it
: backup_scope
)
4791 if (it
.second
== NULL
)
4792 current_scope
.erase(it
.first
);
4794 current_scope
[it
.first
] = it
.second
;
4796 return AstNode::mkconst_bits(variables
.at(str
).val
.bits
, variables
.at(str
).is_signed
);
4799 void AstNode::allocateDefaultEnumValues()
4801 log_assert(type
==AST_ENUM
);
4802 int last_enum_int
= -1;
4803 for (auto node
: children
) {
4804 log_assert(node
->type
==AST_ENUM_ITEM
);
4805 node
->attributes
[ID::enum_base_type
] = mkconst_str(str
);
4806 for (size_t i
= 0; i
< node
->children
.size(); i
++) {
4807 switch (node
->children
[i
]->type
) {
4809 // replace with auto-incremented constant
4810 delete node
->children
[i
];
4811 node
->children
[i
] = AstNode::mkconst_int(++last_enum_int
, true);
4814 // explicit constant (or folded expression)
4815 // TODO: can't extend 'x or 'z item
4816 last_enum_int
= node
->children
[i
]->integer
;
4822 // TODO: range check