2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * This is the AST frontend library.
22 * The AST frontend library is not a frontend on it's own but provides a
23 * generic abstract syntax tree (AST) abstraction for HDL code and can be
24 * used by HDL frontends. See "ast.h" for an overview of the API and the
25 * Verilog frontend for an usage example.
29 #include "kernel/log.h"
30 #include "libs/sha1/sha1.h"
31 #include "frontends/verilog/verilog_frontend.h"
42 using namespace AST_INTERNAL
;
44 // Process a format string and arguments for $display, $write, $sprintf, etc
46 std::string
AstNode::process_format_str(const std::string
&sformat
, int next_arg
, int stage
, int width_hint
, bool sign_hint
) {
47 // Other arguments are placeholders. Process the string as we go through it
49 for (size_t i
= 0; i
< sformat
.length(); i
++)
52 if (sformat
[i
] == '%')
54 // If there's no next character, that's a problem
55 if (i
+1 >= sformat
.length())
56 log_file_error(filename
, location
.first_line
, "System task `%s' called with `%%' at end of string.\n", str
.c_str());
58 char cformat
= sformat
[++i
];
60 // %% is special, does not need a matching argument
68 bool got_zlen
= false;
71 while ('0' <= cformat
&& cformat
<= '9')
73 if (!got_len
&& cformat
== '0')
77 len_value
= 10*len_value
+ (cformat
- '0');
79 cformat
= sformat
[++i
];
82 // Simplify the argument
83 AstNode
*node_arg
= nullptr;
85 // Everything from here on depends on the format specifier
93 goto unsupported_format
;
97 if (next_arg
>= GetSize(children
))
98 log_file_error(filename
, location
.first_line
, "Missing argument for %%%c format specifier in system task `%s'.\n",
99 cformat
, str
.c_str());
101 node_arg
= children
[next_arg
++];
102 while (node_arg
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
103 if (node_arg
->type
!= AST_CONSTANT
)
104 log_file_error(filename
, location
.first_line
, "Failed to evaluate system task `%s' with non-constant argument.\n", str
.c_str());
110 goto unsupported_format
;
115 log_file_error(filename
, location
.first_line
, "System task `%s' called with invalid/unsupported format specifier.\n", str
.c_str());
123 sout
+= node_arg
->bitsAsConst().decode_string();
128 sout
+= stringf("%d", node_arg
->bitsAsConst().as_int());
134 Const val
= node_arg
->bitsAsConst();
136 while (GetSize(val
) % 4 != 0)
137 val
.bits
.push_back(State::S0
);
139 int len
= GetSize(val
) / 4;
140 for (int i
= len
; i
< len_value
; i
++)
141 sout
+= got_zlen
? '0' : ' ';
143 for (int i
= len
-1; i
>= 0; i
--) {
144 Const digit
= val
.extract(4*i
, 4);
145 if (digit
.is_fully_def())
146 sout
+= stringf(cformat
== 'x' ? "%x" : "%X", digit
.as_int());
148 sout
+= cformat
== 'x' ? "x" : "X";
155 sout
+= log_id(current_module
->name
);
163 // not a format specifier
171 void AstNode::annotateTypedEnums(AstNode
*template_node
)
174 if (template_node
->attributes
.count(ID::enum_type
)) {
175 //get reference to enum node:
176 std::string enum_type
= template_node
->attributes
[ID::enum_type
]->str
.c_str();
177 // log("enum_type=%s (count=%lu)\n", enum_type.c_str(), current_scope.count(enum_type));
178 // log("current scope:\n");
179 // for (auto &it : current_scope)
180 // log(" %s\n", it.first.c_str());
181 log_assert(current_scope
.count(enum_type
) == 1);
182 AstNode
*enum_node
= current_scope
.at(enum_type
);
183 log_assert(enum_node
->type
== AST_ENUM
);
184 //get width from 1st enum item:
185 log_assert(enum_node
->children
.size() >= 1);
186 AstNode
*enum_item0
= enum_node
->children
[0];
187 log_assert(enum_item0
->type
== AST_ENUM_ITEM
);
189 if (!enum_item0
->range_valid
)
191 else if (enum_item0
->range_swapped
)
192 width
= enum_item0
->range_right
- enum_item0
->range_left
+ 1;
194 width
= enum_item0
->range_left
- enum_item0
->range_right
+ 1;
195 log_assert(width
> 0);
196 //add declared enum items:
197 for (auto enum_item
: enum_node
->children
){
198 log_assert(enum_item
->type
== AST_ENUM_ITEM
);
201 if (enum_item
->children
.size() == 1){
203 } else if (enum_item
->children
.size() == 2){
204 log_assert(enum_item
->children
[1]->type
== AST_RANGE
);
205 is_signed
= enum_item
->children
[1]->is_signed
;
207 log_error("enum_item children size==%lu, expected 1 or 2 for %s (%s)\n",
208 enum_item
->children
.size(),
209 enum_item
->str
.c_str(), enum_node
->str
.c_str()
212 //start building attribute string
213 std::string enum_item_str
= "\\enum_value_";
214 //get enum item value
215 if(enum_item
->children
[0]->type
!= AST_CONSTANT
){
216 log_error("expected const, got %s for %s (%s)\n",
217 type2str(enum_item
->children
[0]->type
).c_str(),
218 enum_item
->str
.c_str(), enum_node
->str
.c_str()
221 RTLIL::Const val
= enum_item
->children
[0]->bitsAsConst(width
, is_signed
);
222 enum_item_str
.append(val
.as_string());
223 //set attribute for available val to enum item name mappings
224 attributes
[enum_item_str
.c_str()] = mkconst_str(enum_item
->str
);
229 static bool name_has_dot(const std::string
&name
, std::string
&struct_name
)
231 // check if plausible struct member name \sss.mmm
232 std::string::size_type pos
;
233 if (name
.substr(0, 1) == "\\" && (pos
= name
.find('.', 0)) != std::string::npos
) {
234 struct_name
= name
.substr(0, pos
);
240 static AstNode
*make_range(int left
, int right
, bool is_signed
= false)
242 // generate a pre-validated range node for a fixed signal range.
243 auto range
= new AstNode(AST_RANGE
);
244 range
->range_left
= left
;
245 range
->range_right
= right
;
246 range
->range_valid
= true;
247 range
->children
.push_back(AstNode::mkconst_int(left
, true));
248 range
->children
.push_back(AstNode::mkconst_int(right
, true));
249 range
->is_signed
= is_signed
;
253 static AstNode
*make_packed_struct(AstNode
*template_node
, std::string
&name
)
255 // create a wire for the packed struct
256 auto wnode
= new AstNode(AST_WIRE
);
258 wnode
->is_logic
= true;
259 wnode
->range_valid
= true;
260 // get the width from the MS member in the template
261 // as members are laid out from left to right
262 int offset
= template_node
->children
[0]->range_left
;
263 auto range
= make_range(offset
, 0);
264 wnode
->children
.push_back(range
);
265 // make sure this node is the one in scope for this name
266 current_scope
[name
] = wnode
;
267 // add members to scope
268 for (auto *node
: template_node
->children
) {
269 auto member_name
= name
+ "." + node
->str
;
270 current_scope
[member_name
] = node
;
275 // convert the AST into a simpler AST that has all parameters substituted by their
276 // values, unrolled for-loops, expanded generate blocks, etc. when this function
277 // is done with an AST it can be converted into RTLIL using genRTLIL().
279 // this function also does all name resolving and sets the id2ast member of all
280 // nodes that link to a different node using names and lexical scoping.
281 bool AstNode::simplify(bool const_fold
, bool at_zero
, bool in_lvalue
, int stage
, int width_hint
, bool sign_hint
, bool in_param
)
283 static int recursion_counter
= 0;
284 static bool deep_recursion_warning
= false;
286 if (recursion_counter
++ == 1000 && deep_recursion_warning
) {
287 log_warning("Deep recursion in AST simplifier.\nDoes this design contain insanely long expressions?\n");
288 deep_recursion_warning
= false;
291 AstNode
*newNode
= NULL
;
292 bool did_something
= false;
295 log("-------------\n");
296 log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage
, recursion_counter
, filename
.c_str(), location
.first_line
, type2str(type
).c_str(), this);
297 log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
298 int(const_fold
), int(at_zero
), int(in_lvalue
), int(stage
), int(width_hint
), int(sign_hint
), int(in_param
));
299 // dumpAst(NULL, "> ");
304 log_assert(type
== AST_MODULE
|| type
== AST_INTERFACE
);
306 deep_recursion_warning
= true;
307 while (simplify(const_fold
, at_zero
, in_lvalue
, 1, width_hint
, sign_hint
, in_param
)) { }
309 if (!flag_nomem2reg
&& !get_bool_attribute(ID::nomem2reg
))
311 dict
<AstNode
*, pool
<std::string
>> mem2reg_places
;
312 dict
<AstNode
*, uint32_t> mem2reg_candidates
, dummy_proc_flags
;
313 uint32_t flags
= flag_mem2reg
? AstNode::MEM2REG_FL_ALL
: 0;
314 mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, dummy_proc_flags
, flags
);
316 pool
<AstNode
*> mem2reg_set
;
317 for (auto &it
: mem2reg_candidates
)
319 AstNode
*mem
= it
.first
;
320 uint32_t memflags
= it
.second
;
321 bool this_nomeminit
= flag_nomeminit
;
322 log_assert((memflags
& ~0x00ffff00) == 0);
324 if (mem
->get_bool_attribute(ID::nomem2reg
))
327 if (mem
->get_bool_attribute(ID::nomeminit
) || get_bool_attribute(ID::nomeminit
))
328 this_nomeminit
= true;
330 if (memflags
& AstNode::MEM2REG_FL_FORCED
)
331 goto silent_activate
;
333 if (memflags
& AstNode::MEM2REG_FL_EQ2
)
334 goto verbose_activate
;
336 if (memflags
& AstNode::MEM2REG_FL_SET_ASYNC
)
337 goto verbose_activate
;
339 if ((memflags
& AstNode::MEM2REG_FL_SET_INIT
) && (memflags
& AstNode::MEM2REG_FL_SET_ELSE
) && this_nomeminit
)
340 goto verbose_activate
;
342 if (memflags
& AstNode::MEM2REG_FL_CMPLX_LHS
)
343 goto verbose_activate
;
345 if ((memflags
& AstNode::MEM2REG_FL_CONST_LHS
) && !(memflags
& AstNode::MEM2REG_FL_VAR_LHS
))
346 goto verbose_activate
;
348 // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
352 if (mem2reg_set
.count(mem
) == 0) {
353 std::string message
= stringf("Replacing memory %s with list of registers.", mem
->str
.c_str());
354 bool first_element
= true;
355 for (auto &place
: mem2reg_places
[it
.first
]) {
356 message
+= stringf("%s%s", first_element
? " See " : ", ", place
.c_str());
357 first_element
= false;
359 log_warning("%s\n", message
.c_str());
363 // log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
364 mem2reg_set
.insert(mem
);
367 for (auto node
: mem2reg_set
)
369 int mem_width
, mem_size
, addr_bits
;
370 node
->meminfo(mem_width
, mem_size
, addr_bits
);
372 int data_range_left
= node
->children
[0]->range_left
;
373 int data_range_right
= node
->children
[0]->range_right
;
375 if (node
->children
[0]->range_swapped
)
376 std::swap(data_range_left
, data_range_right
);
378 for (int i
= 0; i
< mem_size
; i
++) {
379 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
380 mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
381 reg
->str
= stringf("%s[%d]", node
->str
.c_str(), i
);
383 reg
->is_signed
= node
->is_signed
;
384 for (auto &it
: node
->attributes
)
385 if (it
.first
!= ID::mem2reg
)
386 reg
->attributes
.emplace(it
.first
, it
.second
->clone());
387 reg
->filename
= node
->filename
;
388 reg
->location
= node
->location
;
389 children
.push_back(reg
);
390 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
394 AstNode
*async_block
= NULL
;
395 while (mem2reg_as_needed_pass2(mem2reg_set
, this, NULL
, async_block
)) { }
397 vector
<AstNode
*> delnodes
;
398 mem2reg_remove(mem2reg_set
, delnodes
);
400 for (auto node
: delnodes
)
404 while (simplify(const_fold
, at_zero
, in_lvalue
, 2, width_hint
, sign_hint
, in_param
)) { }
409 current_filename
= filename
;
411 // we do not look inside a task or function
412 // (but as soon as a task or function is instantiated we process the generated AST as usual)
413 if (type
== AST_FUNCTION
|| type
== AST_TASK
) {
418 // deactivate all calls to non-synthesis system tasks
419 // note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
420 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && (str
== "$strobe" || str
== "$monitor" || str
== "$time" ||
421 str
== "$dumpfile" || str
== "$dumpvars" || str
== "$dumpon" || str
== "$dumpoff" || str
== "$dumpall")) {
422 log_file_warning(filename
, location
.first_line
, "Ignoring call to system %s %s.\n", type
== AST_FCALL
? "function" : "task", str
.c_str());
427 if ((type
== AST_TCALL
) && (str
== "$display" || str
== "$write") && (!current_always
|| current_always
->type
!= AST_INITIAL
)) {
428 log_file_warning(filename
, location
.first_line
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
433 // print messages if this a call to $display() or $write()
434 // This code implements only a small subset of Verilog-2005 $display() format specifiers,
435 // but should be good enough for most uses
436 if ((type
== AST_TCALL
) && ((str
== "$display") || (str
== "$write")))
438 int nargs
= GetSize(children
);
440 log_file_error(filename
, location
.first_line
, "System task `%s' got %d arguments, expected >= 1.\n",
441 str
.c_str(), int(children
.size()));
443 // First argument is the format string
444 AstNode
*node_string
= children
[0];
445 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
446 if (node_string
->type
!= AST_CONSTANT
)
447 log_file_error(filename
, location
.first_line
, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str
.c_str());
448 std::string sformat
= node_string
->bitsAsConst().decode_string();
449 std::string sout
= process_format_str(sformat
, 1, stage
, width_hint
, sign_hint
);
450 // Finally, print the message (only include a \n for $display, not for $write)
451 log("%s", sout
.c_str());
452 if (str
== "$display")
458 // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
459 if (type
== AST_WIRE
|| type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_ENUM_ITEM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_RANGE
|| type
== AST_PREFIX
|| type
== AST_TYPEDEF
)
461 if (type
== AST_IDENTIFIER
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
|| current_scope
[str
]->type
== AST_ENUM_ITEM
))
464 // in certain cases a function must be evaluated constant. this is what in_param controls.
465 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_PREFIX
)
468 std::map
<std::string
, AstNode
*> backup_scope
;
470 // create name resolution entries for all objects with names
471 // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
472 if (type
== AST_MODULE
) {
473 current_scope
.clear();
474 std::map
<std::string
, AstNode
*> this_wire_scope
;
475 for (size_t i
= 0; i
< children
.size(); i
++) {
476 AstNode
*node
= children
[i
];
478 if (node
->type
== AST_WIRE
) {
479 if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
480 for (auto c
: node
->children
[0]->children
) {
481 if (!c
->is_simple_const_expr()) {
482 if (attributes
.count(ID::dynports
))
483 delete attributes
.at(ID::dynports
);
484 attributes
[ID::dynports
] = AstNode::mkconst_int(1, true);
488 if (this_wire_scope
.count(node
->str
) > 0) {
489 AstNode
*first_node
= this_wire_scope
[node
->str
];
490 if (first_node
->is_input
&& node
->is_reg
)
491 goto wires_are_incompatible
;
492 if (!node
->is_input
&& !node
->is_output
&& node
->is_reg
&& node
->children
.size() == 0)
493 goto wires_are_compatible
;
494 if (first_node
->children
.size() == 0 && node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
495 AstNode
*r
= node
->children
[0];
496 if (r
->range_valid
&& r
->range_left
== 0 && r
->range_right
== 0) {
498 node
->children
.pop_back();
501 if (first_node
->children
.size() != node
->children
.size())
502 goto wires_are_incompatible
;
503 for (size_t j
= 0; j
< node
->children
.size(); j
++) {
504 AstNode
*n1
= first_node
->children
[j
], *n2
= node
->children
[j
];
505 if (n1
->type
== AST_RANGE
&& n2
->type
== AST_RANGE
&& n1
->range_valid
&& n2
->range_valid
) {
506 if (n1
->range_left
!= n2
->range_left
)
507 goto wires_are_incompatible
;
508 if (n1
->range_right
!= n2
->range_right
)
509 goto wires_are_incompatible
;
510 } else if (*n1
!= *n2
)
511 goto wires_are_incompatible
;
513 if (first_node
->range_left
!= node
->range_left
)
514 goto wires_are_incompatible
;
515 if (first_node
->range_right
!= node
->range_right
)
516 goto wires_are_incompatible
;
517 if (first_node
->port_id
== 0 && (node
->is_input
|| node
->is_output
))
518 goto wires_are_incompatible
;
519 wires_are_compatible
:
521 first_node
->is_input
= true;
523 first_node
->is_output
= true;
525 first_node
->is_reg
= true;
527 first_node
->is_logic
= true;
529 first_node
->is_signed
= true;
530 for (auto &it
: node
->attributes
) {
531 if (first_node
->attributes
.count(it
.first
) > 0)
532 delete first_node
->attributes
[it
.first
];
533 first_node
->attributes
[it
.first
] = it
.second
->clone();
535 children
.erase(children
.begin()+(i
--));
536 did_something
= true;
539 wires_are_incompatible
:
541 log_file_error(filename
, location
.first_line
, "Incompatible re-declaration of wire %s.\n", node
->str
.c_str());
544 this_wire_scope
[node
->str
] = node
;
546 // these nodes appear at the top level in a module and can define names
547 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
548 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
|| node
->type
== AST_CELL
||
549 node
->type
== AST_TYPEDEF
) {
550 backup_scope
[node
->str
] = current_scope
[node
->str
];
551 current_scope
[node
->str
] = node
;
553 if (node
->type
== AST_ENUM
) {
554 current_scope
[node
->str
] = node
;
555 for (auto enode
: node
->children
) {
556 log_assert(enode
->type
==AST_ENUM_ITEM
);
557 if (current_scope
.count(enode
->str
) == 0)
558 current_scope
[enode
->str
] = enode
;
560 log_file_error(filename
, location
.first_line
, "enum item %s already exists\n", enode
->str
.c_str());
564 for (size_t i
= 0; i
< children
.size(); i
++) {
565 AstNode
*node
= children
[i
];
566 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_MEMORY
|| node
->type
== AST_TYPEDEF
)
567 while (node
->simplify(true, false, false, 1, -1, false, node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
))
568 did_something
= true;
569 if (node
->type
== AST_ENUM
) {
570 for (auto enode
YS_ATTRIBUTE(unused
) : node
->children
){
571 log_assert(enode
->type
==AST_ENUM_ITEM
);
572 while (node
->simplify(true, false, false, 1, -1, false, in_param
))
573 did_something
= true;
579 // create name resolution entries for all objects with names
580 if (type
== AST_PACKAGE
) {
581 //add names to package scope
582 for (size_t i
= 0; i
< children
.size(); i
++) {
583 AstNode
*node
= children
[i
];
584 // these nodes appear at the top level in a package and can define names
585 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_TYPEDEF
) {
586 current_scope
[node
->str
] = node
;
588 if (node
->type
== AST_ENUM
) {
589 current_scope
[node
->str
] = node
;
590 for (auto enode
: node
->children
) {
591 log_assert(enode
->type
==AST_ENUM_ITEM
);
592 if (current_scope
.count(enode
->str
) == 0)
593 current_scope
[enode
->str
] = enode
;
595 log_file_error(filename
, location
.first_line
, "enum item %s already exists in package\n", enode
->str
.c_str());
602 auto backup_current_block
= current_block
;
603 auto backup_current_block_child
= current_block_child
;
604 auto backup_current_top_block
= current_top_block
;
605 auto backup_current_always
= current_always
;
606 auto backup_current_always_clocked
= current_always_clocked
;
608 if (type
== AST_ALWAYS
|| type
== AST_INITIAL
)
610 if (current_always
!= nullptr)
611 log_file_error(filename
, location
.first_line
, "Invalid nesting of always blocks and/or initializations.\n");
613 current_always
= this;
614 current_always_clocked
= false;
616 if (type
== AST_ALWAYS
)
617 for (auto child
: children
) {
618 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
619 current_always_clocked
= true;
620 if (child
->type
== AST_EDGE
&& GetSize(child
->children
) == 1 &&
621 child
->children
[0]->type
== AST_IDENTIFIER
&& child
->children
[0]->str
== "\\$global_clock")
622 current_always_clocked
= true;
626 int backup_width_hint
= width_hint
;
627 bool backup_sign_hint
= sign_hint
;
629 bool detect_width_simple
= false;
630 bool child_0_is_self_determined
= false;
631 bool child_1_is_self_determined
= false;
632 bool child_2_is_self_determined
= false;
633 bool children_are_self_determined
= false;
634 bool reset_width_after_children
= false;
641 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, true, stage
, -1, false, in_param
) == true)
642 did_something
= true;
643 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
) == true)
644 did_something
= true;
645 children
[0]->detectSignWidth(backup_width_hint
, backup_sign_hint
);
646 children
[1]->detectSignWidth(width_hint
, sign_hint
);
647 width_hint
= max(width_hint
, backup_width_hint
);
648 child_0_is_self_determined
= true;
649 // test only once, before optimizations and memory mappings but after assignment LHS was mapped to an identifier
650 if (children
[0]->id2ast
&& !children
[0]->was_checked
) {
651 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->id2ast
->is_logic
)
652 children
[0]->id2ast
->is_reg
= true; // if logic type is used in a block asignment
653 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && !children
[0]->id2ast
->is_reg
)
654 log_warning("wire '%s' is assigned in a block at %s:%d.%d-%d.%d.\n", children
[0]->str
.c_str(), filename
.c_str(), location
.first_line
, location
.first_column
, location
.last_line
, location
.last_column
);
655 if (type
== AST_ASSIGN
&& children
[0]->id2ast
->is_reg
) {
656 bool is_rand_reg
= false;
657 if (children
[1]->type
== AST_FCALL
) {
658 if (children
[1]->str
== "\\$anyconst")
660 if (children
[1]->str
== "\\$anyseq")
662 if (children
[1]->str
== "\\$allconst")
664 if (children
[1]->str
== "\\$allseq")
668 log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.%d-%d.%d.\n", children
[0]->str
.c_str(), filename
.c_str(), location
.first_line
, location
.first_column
, location
.last_line
, location
.last_column
);
670 children
[0]->was_checked
= true;
675 //log("STRUCT %d %d %d\n", stage, basic_prep, in_param);
677 //dumpAst(NULL, "1> ");
678 for (auto *node
: children
) {
679 // resolve any ranges
680 while (!node
->basic_prep
&& node
->simplify(true, false, false, stage
, -1, false, false)) {
681 did_something
= true;
685 // The members will be laid out in the structure contiguously from left to right.
686 // Determine total packed size and assign offsets. Store these in the member node.
687 // dumpAst(NULL, "2> ");
689 for (auto it
= children
.rbegin(); it
!= children
.rend(); ++it
) {
692 node
->is_signed
= true;
694 if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
695 auto rnode
= node
->children
[0];
696 width
= (rnode
->range_swapped
? rnode
->range_right
- rnode
->range_left
:
697 rnode
->range_left
- rnode
->range_right
) + 1;
698 // range nodes are now redundant
699 node
->children
.clear();
704 node
->range_right
= offset
;
705 node
->range_left
= offset
+ width
- 1;
706 node
->range_valid
= true;
710 // instance rather than just a type in a typedef
711 // so add a wire for the packed structure
712 auto wnode
= make_packed_struct(this, str
);
713 current_ast_mod
->children
.push_back(wnode
);
718 case AST_STRUCT_ITEM
:
722 //log("\nENUM %s: %d child %d\n", str.c_str(), basic_prep, children[0]->basic_prep);
724 for (auto item_node
: children
) {
725 while (!item_node
->basic_prep
&& item_node
->simplify(false, false, false, stage
, -1, false, in_param
))
726 did_something
= true;
728 // allocate values (called more than once)
729 allocateDefaultEnumValues();
735 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, true) == true)
736 did_something
= true;
737 children
[0]->detectSignWidth(width_hint
, sign_hint
);
738 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
739 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, true) == true)
740 did_something
= true;
741 if (!children
[1]->range_valid
)
742 log_file_error(filename
, location
.first_line
, "Non-constant width range on parameter decl.\n");
743 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
747 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, in_param
))
748 did_something
= true;
749 children
[0]->detectSignWidth(width_hint
, sign_hint
);
750 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
751 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
))
752 did_something
= true;
753 if (!children
[1]->range_valid
)
754 log_file_error(filename
, location
.first_line
, "Non-constant width range on enum item decl.\n");
755 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
761 case AST_TO_UNSIGNED
:
768 case AST_REDUCE_XNOR
:
769 case AST_REDUCE_BOOL
:
770 detect_width_simple
= true;
771 children_are_self_determined
= true;
786 detect_width_simple
= true;
790 case AST_SHIFT_RIGHT
:
791 case AST_SHIFT_SLEFT
:
792 case AST_SHIFT_SRIGHT
:
794 detect_width_simple
= true;
795 child_1_is_self_determined
= true;
808 for (auto child
: children
) {
809 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
810 did_something
= true;
811 child
->detectSignWidthWorker(width_hint
, sign_hint
);
813 reset_width_after_children
= true;
819 detect_width_simple
= true;
820 children_are_self_determined
= true;
824 detect_width_simple
= true;
825 child_0_is_self_determined
= true;
829 detect_width_simple
= true;
830 children_are_self_determined
= true;
835 children_are_self_determined
= true;
843 if (detect_width_simple
&& width_hint
< 0) {
844 if (type
== AST_REPLICATE
)
845 while (children
[0]->simplify(true, false, in_lvalue
, stage
, -1, false, true) == true)
846 did_something
= true;
847 for (auto child
: children
)
848 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
849 did_something
= true;
850 detectSignWidth(width_hint
, sign_hint
);
853 if (type
== AST_FCALL
&& str
== "\\$past")
854 detectSignWidth(width_hint
, sign_hint
);
856 if (type
== AST_TERNARY
) {
857 int width_hint_left
, width_hint_right
;
858 bool sign_hint_left
, sign_hint_right
;
859 bool found_real_left
, found_real_right
;
860 children
[1]->detectSignWidth(width_hint_left
, sign_hint_left
, &found_real_left
);
861 children
[2]->detectSignWidth(width_hint_right
, sign_hint_right
, &found_real_right
);
862 if (found_real_left
|| found_real_right
) {
863 child_1_is_self_determined
= true;
864 child_2_is_self_determined
= true;
868 if (type
== AST_CONDX
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
869 for (auto &bit
: children
.at(0)->bits
)
870 if (bit
== State::Sz
|| bit
== State::Sx
)
874 if (type
== AST_CONDZ
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
875 for (auto &bit
: children
.at(0)->bits
)
876 if (bit
== State::Sz
)
880 if (const_fold
&& type
== AST_CASE
)
882 while (children
[0]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
883 if (children
[0]->type
== AST_CONSTANT
&& children
[0]->bits_only_01()) {
884 std::vector
<AstNode
*> new_children
;
885 new_children
.push_back(children
[0]);
886 for (int i
= 1; i
< GetSize(children
); i
++) {
887 AstNode
*child
= children
[i
];
888 log_assert(child
->type
== AST_COND
|| child
->type
== AST_CONDX
|| child
->type
== AST_CONDZ
);
889 for (auto v
: child
->children
) {
890 if (v
->type
== AST_DEFAULT
)
891 goto keep_const_cond
;
892 if (v
->type
== AST_BLOCK
)
894 while (v
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
895 if (v
->type
== AST_CONSTANT
&& v
->bits_only_01()) {
896 if (v
->bits
== children
[0]->bits
) {
897 while (i
+1 < GetSize(children
))
898 delete children
[++i
];
899 goto keep_const_cond
;
903 goto keep_const_cond
;
907 new_children
.push_back(child
);
911 new_children
.swap(children
);
915 // simplify all children first
916 // (iterate by index as e.g. auto wires can add new children in the process)
917 for (size_t i
= 0; i
< children
.size(); i
++) {
918 bool did_something_here
= true;
919 bool backup_flag_autowire
= flag_autowire
;
920 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && i
>= 3)
922 if ((type
== AST_GENIF
|| type
== AST_GENCASE
) && i
>= 1)
924 if (type
== AST_GENBLOCK
)
926 if (type
== AST_BLOCK
&& !str
.empty())
928 if (type
== AST_PREFIX
&& i
>= 1)
930 if (type
== AST_DEFPARAM
&& i
== 0)
931 flag_autowire
= true;
932 while (did_something_here
&& i
< children
.size()) {
933 bool const_fold_here
= const_fold
, in_lvalue_here
= in_lvalue
;
934 int width_hint_here
= width_hint
;
935 bool sign_hint_here
= sign_hint
;
936 bool in_param_here
= in_param
;
937 if (i
== 0 && (type
== AST_REPLICATE
|| type
== AST_WIRE
))
938 const_fold_here
= true, in_param_here
= true;
939 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
)
940 const_fold_here
= true;
941 if (i
== 0 && (type
== AST_ASSIGN
|| type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
))
942 in_lvalue_here
= true;
943 if (type
== AST_BLOCK
) {
944 current_block
= this;
945 current_block_child
= children
[i
];
947 if ((type
== AST_ALWAYS
|| type
== AST_INITIAL
) && children
[i
]->type
== AST_BLOCK
)
948 current_top_block
= children
[i
];
949 if (i
== 0 && child_0_is_self_determined
)
950 width_hint_here
= -1, sign_hint_here
= false;
951 if (i
== 1 && child_1_is_self_determined
)
952 width_hint_here
= -1, sign_hint_here
= false;
953 if (i
== 2 && child_2_is_self_determined
)
954 width_hint_here
= -1, sign_hint_here
= false;
955 if (children_are_self_determined
)
956 width_hint_here
= -1, sign_hint_here
= false;
957 did_something_here
= children
[i
]->simplify(const_fold_here
, at_zero
, in_lvalue_here
, stage
, width_hint_here
, sign_hint_here
, in_param_here
);
958 if (did_something_here
)
959 did_something
= true;
961 if (stage
== 2 && children
[i
]->type
== AST_INITIAL
&& current_ast_mod
!= this) {
962 current_ast_mod
->children
.push_back(children
[i
]);
963 children
.erase(children
.begin() + (i
--));
964 did_something
= true;
966 flag_autowire
= backup_flag_autowire
;
968 for (auto &attr
: attributes
) {
969 while (attr
.second
->simplify(true, false, false, stage
, -1, false, true))
970 did_something
= true;
973 if (reset_width_after_children
) {
974 width_hint
= backup_width_hint
;
975 sign_hint
= backup_sign_hint
;
977 detectSignWidth(width_hint
, sign_hint
);
980 current_block
= backup_current_block
;
981 current_block_child
= backup_current_block_child
;
982 current_top_block
= backup_current_top_block
;
983 current_always
= backup_current_always
;
984 current_always_clocked
= backup_current_always_clocked
;
986 for (auto it
= backup_scope
.begin(); it
!= backup_scope
.end(); it
++) {
987 if (it
->second
== NULL
)
988 current_scope
.erase(it
->first
);
990 current_scope
[it
->first
] = it
->second
;
993 current_filename
= filename
;
995 if (type
== AST_MODULE
)
996 current_scope
.clear();
998 // convert defparam nodes to cell parameters
999 if (type
== AST_DEFPARAM
&& !children
.empty())
1001 if (children
[0]->type
!= AST_IDENTIFIER
)
1002 log_file_error(filename
, location
.first_line
, "Module name in defparam contains non-constant expressions!\n");
1004 string modname
, paramname
= children
[0]->str
;
1006 size_t pos
= paramname
.rfind('.');
1008 while (pos
!= 0 && pos
!= std::string::npos
)
1010 modname
= paramname
.substr(0, pos
);
1012 if (current_scope
.count(modname
))
1015 pos
= paramname
.rfind('.', pos
- 1);
1018 if (pos
== std::string::npos
)
1019 log_file_error(filename
, location
.first_line
, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname
).c_str());
1021 paramname
= "\\" + paramname
.substr(pos
+1);
1023 if (current_scope
.at(modname
)->type
!= AST_CELL
)
1024 log_file_error(filename
, location
.first_line
, "Defparam argument `%s . %s` does not match a cell!\n",
1025 RTLIL::unescape_id(modname
).c_str(), RTLIL::unescape_id(paramname
).c_str());
1027 AstNode
*paraset
= new AstNode(AST_PARASET
, children
[1]->clone(), GetSize(children
) > 2 ? children
[2]->clone() : NULL
);
1028 paraset
->str
= paramname
;
1030 AstNode
*cell
= current_scope
.at(modname
);
1031 cell
->children
.insert(cell
->children
.begin() + 1, paraset
);
1036 if (type
== AST_TYPEDEF
) {
1037 log_assert(children
.size() == 1);
1038 auto type_node
= children
[0];
1039 log_assert(type_node
->type
== AST_WIRE
|| type_node
->type
== AST_MEMORY
|| type_node
->type
== AST_STRUCT
);
1040 while (type_node
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {
1041 did_something
= true;
1043 log_assert(!type_node
->is_custom_type
);
1046 // resolve types of wires
1047 if (type
== AST_WIRE
|| type
== AST_MEMORY
) {
1048 if (is_custom_type
) {
1049 log_assert(children
.size() >= 1);
1050 log_assert(children
[0]->type
== AST_WIRETYPE
);
1051 auto type_name
= children
[0]->str
;
1052 if (!current_scope
.count(type_name
)) {
1053 log_file_error(filename
, location
.first_line
, "Unknown identifier `%s' used as type name\n", type_name
.c_str());
1055 AstNode
*resolved_type_node
= current_scope
.at(type_name
);
1056 if (resolved_type_node
->type
!= AST_TYPEDEF
)
1057 log_file_error(filename
, location
.first_line
, "`%s' does not name a type\n", type_name
.c_str());
1058 log_assert(resolved_type_node
->children
.size() == 1);
1059 AstNode
*template_node
= resolved_type_node
->children
[0];
1061 // Ensure typedef itself is fully simplified
1062 while (template_node
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
1064 if (template_node
->type
== AST_STRUCT
) {
1065 // replace with wire representing the packed structure
1066 newNode
= make_packed_struct(template_node
, str
);
1067 current_scope
[str
] = this;
1071 // Remove type reference
1073 children
.erase(children
.begin());
1075 if (type
== AST_WIRE
)
1076 type
= template_node
->type
;
1077 is_reg
= template_node
->is_reg
;
1078 is_logic
= template_node
->is_logic
;
1079 is_signed
= template_node
->is_signed
;
1080 is_string
= template_node
->is_string
;
1081 is_custom_type
= template_node
->is_custom_type
;
1083 range_valid
= template_node
->range_valid
;
1084 range_swapped
= template_node
->range_swapped
;
1085 range_left
= template_node
->range_left
;
1086 range_right
= template_node
->range_right
;
1088 attributes
[ID::wiretype
] = mkconst_str(resolved_type_node
->str
);
1090 // if an enum then add attributes to support simulator tracing
1091 annotateTypedEnums(template_node
);
1093 // Insert clones children from template at beginning
1094 for (int i
= 0; i
< GetSize(template_node
->children
); i
++)
1095 children
.insert(children
.begin() + i
, template_node
->children
[i
]->clone());
1097 if (type
== AST_MEMORY
&& GetSize(children
) == 1) {
1098 // Single-bit memories must have [0:0] range
1099 AstNode
*rng
= make_range(0, 0);
1100 children
.insert(children
.begin(), rng
);
1102 did_something
= true;
1104 log_assert(!is_custom_type
);
1107 // resolve types of parameters
1108 if (type
== AST_LOCALPARAM
|| type
== AST_PARAMETER
) {
1109 if (is_custom_type
) {
1110 log_assert(children
.size() == 2);
1111 log_assert(children
[1]->type
== AST_WIRETYPE
);
1112 if (!current_scope
.count(children
[1]->str
))
1113 log_file_error(filename
, location
.first_line
, "Unknown identifier `%s' used as type name\n", children
[1]->str
.c_str());
1114 AstNode
*resolved_type_node
= current_scope
.at(children
[1]->str
);
1115 if (resolved_type_node
->type
!= AST_TYPEDEF
)
1116 log_file_error(filename
, location
.first_line
, "`%s' does not name a type\n", children
[1]->str
.c_str());
1117 log_assert(resolved_type_node
->children
.size() == 1);
1118 AstNode
*template_node
= resolved_type_node
->children
[0];
1120 children
.pop_back();
1122 // Ensure typedef itself is fully simplified
1123 while(template_node
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
1125 if (template_node
->type
== AST_MEMORY
)
1126 log_file_error(filename
, location
.first_line
, "unpacked array type `%s' cannot be used for a parameter\n", children
[1]->str
.c_str());
1127 is_signed
= template_node
->is_signed
;
1128 is_string
= template_node
->is_string
;
1129 is_custom_type
= template_node
->is_custom_type
;
1131 range_valid
= template_node
->range_valid
;
1132 range_swapped
= template_node
->range_swapped
;
1133 range_left
= template_node
->range_left
;
1134 range_right
= template_node
->range_right
;
1135 attributes
[ID::wiretype
] = mkconst_str(resolved_type_node
->str
);
1136 for (auto template_child
: template_node
->children
)
1137 children
.push_back(template_child
->clone());
1138 did_something
= true;
1140 log_assert(!is_custom_type
);
1143 // resolve constant prefixes
1144 if (type
== AST_PREFIX
) {
1145 if (children
[0]->type
!= AST_CONSTANT
) {
1146 // dumpAst(NULL, "> ");
1147 log_file_error(filename
, location
.first_line
, "Index in generate block prefix syntax is not constant!\n");
1149 if (children
[1]->type
== AST_PREFIX
)
1150 children
[1]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
);
1151 log_assert(children
[1]->type
== AST_IDENTIFIER
);
1152 newNode
= children
[1]->clone();
1153 const char *second_part
= children
[1]->str
.c_str();
1154 if (second_part
[0] == '\\')
1156 newNode
->str
= stringf("%s[%d].%s", str
.c_str(), children
[0]->integer
, second_part
);
1160 // evaluate TO_BITS nodes
1161 if (type
== AST_TO_BITS
) {
1162 if (children
[0]->type
!= AST_CONSTANT
)
1163 log_file_error(filename
, location
.first_line
, "Left operand of to_bits expression is not constant!\n");
1164 if (children
[1]->type
!= AST_CONSTANT
)
1165 log_file_error(filename
, location
.first_line
, "Right operand of to_bits expression is not constant!\n");
1166 RTLIL::Const new_value
= children
[1]->bitsAsConst(children
[0]->bitsAsConst().as_int(), children
[1]->is_signed
);
1167 newNode
= mkconst_bits(new_value
.bits
, children
[1]->is_signed
);
1171 // annotate constant ranges
1172 if (type
== AST_RANGE
) {
1173 bool old_range_valid
= range_valid
;
1174 range_valid
= false;
1175 range_swapped
= false;
1178 log_assert(children
.size() >= 1);
1179 if (children
[0]->type
== AST_CONSTANT
) {
1181 range_left
= children
[0]->integer
;
1182 if (children
.size() == 1)
1183 range_right
= range_left
;
1185 if (children
.size() >= 2) {
1186 if (children
[1]->type
== AST_CONSTANT
)
1187 range_right
= children
[1]->integer
;
1189 range_valid
= false;
1191 if (old_range_valid
!= range_valid
)
1192 did_something
= true;
1193 if (range_valid
&& range_left
>= 0 && range_right
> range_left
) {
1194 int tmp
= range_right
;
1195 range_right
= range_left
;
1197 range_swapped
= true;
1201 // annotate wires with their ranges
1202 if (type
== AST_WIRE
) {
1203 if (children
.size() > 0) {
1204 if (children
[0]->range_valid
) {
1206 did_something
= true;
1208 range_swapped
= children
[0]->range_swapped
;
1209 range_left
= children
[0]->range_left
;
1210 range_right
= children
[0]->range_right
;
1214 did_something
= true;
1216 range_swapped
= false;
1222 // resolve multiranges on memory decl
1223 if (type
== AST_MEMORY
&& children
.size() > 1 && children
[1]->type
== AST_MULTIRANGE
)
1226 multirange_dimensions
.clear();
1227 for (auto range
: children
[1]->children
) {
1228 if (!range
->range_valid
)
1229 log_file_error(filename
, location
.first_line
, "Non-constant range on memory decl.\n");
1230 multirange_dimensions
.push_back(min(range
->range_left
, range
->range_right
));
1231 multirange_dimensions
.push_back(max(range
->range_left
, range
->range_right
) - min(range
->range_left
, range
->range_right
) + 1);
1232 total_size
*= multirange_dimensions
.back();
1235 children
[1] = new AstNode(AST_RANGE
, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size
-1, true));
1236 did_something
= true;
1239 // resolve multiranges on memory access
1240 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
&& children
.size() > 0 && children
[0]->type
== AST_MULTIRANGE
)
1242 AstNode
*index_expr
= nullptr;
1244 for (int i
= 0; 2*i
< GetSize(id2ast
->multirange_dimensions
); i
++)
1246 if (GetSize(children
[0]->children
) < i
)
1247 log_file_error(filename
, location
.first_line
, "Insufficient number of array indices for %s.\n", log_id(str
));
1249 AstNode
*new_index_expr
= children
[0]->children
[i
]->children
.at(0)->clone();
1251 if (id2ast
->multirange_dimensions
[2*i
])
1252 new_index_expr
= new AstNode(AST_SUB
, new_index_expr
, AstNode::mkconst_int(id2ast
->multirange_dimensions
[2*i
], true));
1255 index_expr
= new_index_expr
;
1257 index_expr
= new AstNode(AST_ADD
, new AstNode(AST_MUL
, index_expr
, AstNode::mkconst_int(id2ast
->multirange_dimensions
[2*i
+1], true)), new_index_expr
);
1260 for (int i
= GetSize(id2ast
->multirange_dimensions
)/2; i
< GetSize(children
[0]->children
); i
++)
1261 children
.push_back(children
[0]->children
[i
]->clone());
1264 if (index_expr
== nullptr)
1265 children
.erase(children
.begin());
1267 children
[0] = new AstNode(AST_RANGE
, index_expr
);
1269 did_something
= true;
1272 // trim/extend parameters
1273 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_ENUM_ITEM
) {
1274 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
1275 if (!children
[1]->range_valid
)
1276 log_file_error(filename
, location
.first_line
, "Non-constant width range on parameter decl.\n");
1277 int width
= std::abs(children
[1]->range_left
- children
[1]->range_right
) + 1;
1278 if (children
[0]->type
== AST_REALVALUE
) {
1279 RTLIL::Const constvalue
= children
[0]->realAsConst(width
);
1280 log_file_warning(filename
, location
.first_line
, "converting real value %e to binary %s.\n",
1281 children
[0]->realvalue
, log_signal(constvalue
));
1283 children
[0] = mkconst_bits(constvalue
.bits
, sign_hint
);
1284 did_something
= true;
1286 if (children
[0]->type
== AST_CONSTANT
) {
1287 if (width
!= int(children
[0]->bits
.size())) {
1288 RTLIL::SigSpec
sig(children
[0]->bits
);
1289 sig
.extend_u0(width
, children
[0]->is_signed
);
1290 AstNode
*old_child_0
= children
[0];
1291 children
[0] = mkconst_bits(sig
.as_const().bits
, is_signed
);
1294 children
[0]->is_signed
= is_signed
;
1297 range_swapped
= children
[1]->range_swapped
;
1298 range_left
= children
[1]->range_left
;
1299 range_right
= children
[1]->range_right
;
1301 if (children
.size() > 1 && children
[1]->type
== AST_REALVALUE
&& children
[0]->type
== AST_CONSTANT
) {
1302 double as_realvalue
= children
[0]->asReal(sign_hint
);
1304 children
[0] = new AstNode(AST_REALVALUE
);
1305 children
[0]->realvalue
= as_realvalue
;
1306 did_something
= true;
1310 // annotate identifiers using scope resolution and create auto-wires as needed
1311 if (type
== AST_IDENTIFIER
&& !basic_prep
) {
1312 // check if a plausible struct member sss.mmmm
1314 if (name_has_dot(str
, sname
) && children
.size() == 0) {
1316 if (current_scope
.count(str
) > 0) {
1317 auto item_node
= current_scope
[str
];
1318 if (item_node
->type
== AST_STRUCT_ITEM
) {
1319 //log("found struct item %s\n", item_node->str.c_str());
1320 // structure member, rewrite this node to reference the packed struct wire
1321 auto range
= make_range(item_node
->range_left
, item_node
->range_right
);
1322 newNode
= new AstNode(AST_IDENTIFIER
, range
);
1323 newNode
->str
= sname
;
1324 //newNode->dumpAst(NULL, "* ");
1325 newNode
->basic_prep
= true;
1331 if (type
== AST_IDENTIFIER
) {
1332 //log("annotate ID %s, stage=%d cf=%d, ip=%d\n", str.c_str(), stage, const_fold, in_param);
1334 if (current_scope
.count(str
) == 0) {
1335 AstNode
*current_scope_ast
= (current_ast_mod
== nullptr) ? current_ast
: current_ast_mod
;
1336 for (auto node
: current_scope_ast
->children
) {
1337 //log("looking at mod scope child %s\n", type2str(node->type).c_str());
1338 switch (node
->type
) {
1340 case AST_LOCALPARAM
:
1347 case AST_DPI_FUNCTION
:
1348 //log("found child %s, %s\n", type2str(node->type).c_str(), node->str.c_str());
1349 if (str
== node
->str
) {
1350 //log("add %s, type %s to scope\n", str.c_str(), type2str(node->type).c_str());
1351 current_scope
[node
->str
] = node
;
1355 current_scope
[node
->str
] = node
;
1356 for (auto enum_node
: node
->children
) {
1357 log_assert(enum_node
->type
==AST_ENUM_ITEM
);
1358 if (str
== enum_node
->str
) {
1359 //log("\nadding enum item %s to scope\n", str.c_str());
1360 current_scope
[str
] = enum_node
;
1369 if (current_scope
.count(str
) == 0) {
1370 if (current_ast_mod
== nullptr) {
1371 log_file_error(filename
, location
.first_line
, "Identifier `%s' is implicitly declared outside of a module.\n", str
.c_str());
1372 } else if (flag_autowire
|| str
== "\\$global_clock") {
1373 AstNode
*auto_wire
= new AstNode(AST_AUTOWIRE
);
1374 auto_wire
->str
= str
;
1375 current_ast_mod
->children
.push_back(auto_wire
);
1376 current_scope
[str
] = auto_wire
;
1377 did_something
= true;
1379 log_file_error(filename
, location
.first_line
, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str
.c_str());
1382 if (id2ast
!= current_scope
[str
]) {
1383 id2ast
= current_scope
[str
];
1384 did_something
= true;
1388 // split memory access with bit select to individual statements
1389 if (type
== AST_IDENTIFIER
&& children
.size() == 2 && children
[0]->type
== AST_RANGE
&& children
[1]->type
== AST_RANGE
&& !in_lvalue
)
1391 if (id2ast
== NULL
|| id2ast
->type
!= AST_MEMORY
|| children
[0]->children
.size() != 1)
1392 log_file_error(filename
, location
.first_line
, "Invalid bit-select on memory access!\n");
1394 int mem_width
, mem_size
, addr_bits
;
1395 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
1397 int data_range_left
= id2ast
->children
[0]->range_left
;
1398 int data_range_right
= id2ast
->children
[0]->range_right
;
1400 if (id2ast
->children
[0]->range_swapped
)
1401 std::swap(data_range_left
, data_range_right
);
1403 std::stringstream sstr
;
1404 sstr
<< "$mem2bits$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
1405 std::string wire_id
= sstr
.str();
1407 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
1408 wire
->str
= wire_id
;
1410 wire
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
1411 current_ast_mod
->children
.push_back(wire
);
1412 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
1414 AstNode
*data
= clone();
1415 delete data
->children
[1];
1416 data
->children
.pop_back();
1418 AstNode
*assign
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), data
);
1419 assign
->children
[0]->str
= wire_id
;
1420 assign
->children
[0]->was_checked
= true;
1424 size_t assign_idx
= 0;
1425 while (assign_idx
< current_block
->children
.size() && current_block
->children
[assign_idx
] != current_block_child
)
1427 log_assert(assign_idx
< current_block
->children
.size());
1428 current_block
->children
.insert(current_block
->children
.begin()+assign_idx
, assign
);
1429 wire
->is_reg
= true;
1433 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
1434 proc
->children
[0]->children
.push_back(assign
);
1435 current_ast_mod
->children
.push_back(proc
);
1438 newNode
= new AstNode(AST_IDENTIFIER
, children
[1]->clone());
1439 newNode
->str
= wire_id
;
1440 newNode
->id2ast
= wire
;
1444 if (type
== AST_WHILE
)
1445 log_file_error(filename
, location
.first_line
, "While loops are only allowed in constant functions!\n");
1447 if (type
== AST_REPEAT
)
1449 AstNode
*count
= children
[0];
1450 AstNode
*body
= children
[1];
1452 // eval count expression
1453 while (count
->simplify(true, false, false, stage
, 32, true, false)) { }
1455 if (count
->type
!= AST_CONSTANT
)
1456 log_file_error(filename
, location
.first_line
, "Repeat loops outside must have constant repeat counts!\n");
1458 // convert to a block with the body repeated n times
1461 for (int i
= 0; i
< count
->bitsAsConst().as_int(); i
++)
1462 children
.insert(children
.begin(), body
->clone());
1466 did_something
= true;
1469 // unroll for loops and generate-for blocks
1470 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && children
.size() != 0)
1472 AstNode
*init_ast
= children
[0];
1473 AstNode
*while_ast
= children
[1];
1474 AstNode
*next_ast
= children
[2];
1475 AstNode
*body_ast
= children
[3];
1477 while (body_ast
->type
== AST_GENBLOCK
&& body_ast
->str
.empty() &&
1478 body_ast
->children
.size() == 1 && body_ast
->children
.at(0)->type
== AST_GENBLOCK
)
1479 body_ast
= body_ast
->children
.at(0);
1481 if (init_ast
->type
!= AST_ASSIGN_EQ
)
1482 log_file_error(filename
, location
.first_line
, "Unsupported 1st expression of generate for-loop!\n");
1483 if (next_ast
->type
!= AST_ASSIGN_EQ
)
1484 log_file_error(filename
, location
.first_line
, "Unsupported 3rd expression of generate for-loop!\n");
1486 if (type
== AST_GENFOR
) {
1487 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
1488 log_file_error(filename
, location
.first_line
, "Left hand side of 1st expression of generate for-loop is not a gen var!\n");
1489 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
1490 log_file_error(filename
, location
.first_line
, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n");
1492 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1493 log_file_error(filename
, location
.first_line
, "Left hand side of 1st expression of generate for-loop is not a register!\n");
1494 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1495 log_file_error(filename
, location
.first_line
, "Left hand side of 3rd expression of generate for-loop is not a register!\n");
1498 if (init_ast
->children
[0]->id2ast
!= next_ast
->children
[0]->id2ast
)
1499 log_file_error(filename
, location
.first_line
, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n");
1501 // eval 1st expression
1502 AstNode
*varbuf
= init_ast
->children
[1]->clone();
1504 int expr_width_hint
= -1;
1505 bool expr_sign_hint
= true;
1506 varbuf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1507 while (varbuf
->simplify(true, false, false, stage
, 32, true, false)) { }
1510 if (varbuf
->type
!= AST_CONSTANT
)
1511 log_file_error(filename
, location
.first_line
, "Right hand side of 1st expression of generate for-loop is not constant!\n");
1513 auto resolved
= current_scope
.at(init_ast
->children
[0]->str
);
1514 if (resolved
->range_valid
) {
1515 int const_size
= varbuf
->range_left
- varbuf
->range_right
;
1516 int resolved_size
= resolved
->range_left
- resolved
->range_right
;
1517 if (const_size
< resolved_size
) {
1518 for (int i
= const_size
; i
< resolved_size
; i
++)
1519 varbuf
->bits
.push_back(resolved
->is_signed
? varbuf
->bits
.back() : State::S0
);
1520 varbuf
->range_left
= resolved
->range_left
;
1521 varbuf
->range_right
= resolved
->range_right
;
1522 varbuf
->range_swapped
= resolved
->range_swapped
;
1523 varbuf
->range_valid
= resolved
->range_valid
;
1527 varbuf
= new AstNode(AST_LOCALPARAM
, varbuf
);
1528 varbuf
->str
= init_ast
->children
[0]->str
;
1530 AstNode
*backup_scope_varbuf
= current_scope
[varbuf
->str
];
1531 current_scope
[varbuf
->str
] = varbuf
;
1533 size_t current_block_idx
= 0;
1534 if (type
== AST_FOR
) {
1535 while (current_block_idx
< current_block
->children
.size() &&
1536 current_block
->children
[current_block_idx
] != current_block_child
)
1537 current_block_idx
++;
1542 // eval 2nd expression
1543 AstNode
*buf
= while_ast
->clone();
1545 int expr_width_hint
= -1;
1546 bool expr_sign_hint
= true;
1547 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1548 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, false)) { }
1551 if (buf
->type
!= AST_CONSTANT
)
1552 log_file_error(filename
, location
.first_line
, "2nd expression of generate for-loop is not constant!\n");
1554 if (buf
->integer
== 0) {
1561 int index
= varbuf
->children
[0]->integer
;
1562 if (body_ast
->type
== AST_GENBLOCK
)
1563 buf
= body_ast
->clone();
1565 buf
= new AstNode(AST_GENBLOCK
, body_ast
->clone());
1566 if (buf
->str
.empty()) {
1567 std::stringstream sstr
;
1568 sstr
<< "$genblock$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
1569 buf
->str
= sstr
.str();
1571 std::map
<std::string
, std::string
> name_map
;
1572 std::stringstream sstr
;
1573 sstr
<< buf
->str
<< "[" << index
<< "].";
1574 buf
->expand_genblock(varbuf
->str
, sstr
.str(), name_map
);
1576 if (type
== AST_GENFOR
) {
1577 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1578 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1579 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1582 for (size_t i
= 0; i
< buf
->children
.size(); i
++)
1583 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
->children
[i
]);
1585 buf
->children
.clear();
1588 // eval 3rd expression
1589 buf
= next_ast
->children
[1]->clone();
1591 int expr_width_hint
= -1;
1592 bool expr_sign_hint
= true;
1593 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1594 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, true)) { }
1597 if (buf
->type
!= AST_CONSTANT
)
1598 log_file_error(filename
, location
.first_line
, "Right hand side of 3rd expression of generate for-loop is not constant (%s)!\n", type2str(buf
->type
).c_str());
1600 delete varbuf
->children
[0];
1601 varbuf
->children
[0] = buf
;
1604 if (type
== AST_FOR
) {
1605 AstNode
*buf
= next_ast
->clone();
1606 delete buf
->children
[1];
1607 buf
->children
[1] = varbuf
->children
[0]->clone();
1608 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
);
1611 current_scope
[varbuf
->str
] = backup_scope_varbuf
;
1614 did_something
= true;
1617 // check for local objects in unnamed block
1618 if (type
== AST_BLOCK
&& str
.empty())
1620 for (size_t i
= 0; i
< children
.size(); i
++)
1621 if (children
[i
]->type
== AST_WIRE
|| children
[i
]->type
== AST_MEMORY
|| children
[i
]->type
== AST_PARAMETER
|| children
[i
]->type
== AST_LOCALPARAM
|| children
[i
]->type
== AST_TYPEDEF
)
1622 log_file_error(children
[i
]->filename
, children
[i
]->location
.first_line
, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
1625 // transform block with name
1626 if (type
== AST_BLOCK
&& !str
.empty())
1628 std::map
<std::string
, std::string
> name_map
;
1629 expand_genblock(std::string(), str
+ ".", name_map
);
1631 std::vector
<AstNode
*> new_children
;
1632 for (size_t i
= 0; i
< children
.size(); i
++)
1633 if (children
[i
]->type
== AST_WIRE
|| children
[i
]->type
== AST_MEMORY
|| children
[i
]->type
== AST_PARAMETER
|| children
[i
]->type
== AST_LOCALPARAM
|| children
[i
]->type
== AST_TYPEDEF
) {
1634 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1635 current_ast_mod
->children
.push_back(children
[i
]);
1636 current_scope
[children
[i
]->str
] = children
[i
];
1638 new_children
.push_back(children
[i
]);
1640 children
.swap(new_children
);
1641 did_something
= true;
1645 // simplify unconditional generate block
1646 if (type
== AST_GENBLOCK
&& children
.size() != 0)
1649 std::map
<std::string
, std::string
> name_map
;
1650 expand_genblock(std::string(), str
+ ".", name_map
);
1653 for (size_t i
= 0; i
< children
.size(); i
++) {
1654 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1655 current_ast_mod
->children
.push_back(children
[i
]);
1659 did_something
= true;
1662 // simplify generate-if blocks
1663 if (type
== AST_GENIF
&& children
.size() != 0)
1665 AstNode
*buf
= children
[0]->clone();
1666 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1667 if (buf
->type
!= AST_CONSTANT
) {
1668 // for (auto f : log_files)
1669 // dumpAst(f, "verilog-ast> ");
1670 log_file_error(filename
, location
.first_line
, "Condition for generate if is not constant!\n");
1672 if (buf
->asBool() != 0) {
1674 buf
= children
[1]->clone();
1677 buf
= children
.size() > 2 ? children
[2]->clone() : NULL
;
1682 if (buf
->type
!= AST_GENBLOCK
)
1683 buf
= new AstNode(AST_GENBLOCK
, buf
);
1685 if (!buf
->str
.empty()) {
1686 std::map
<std::string
, std::string
> name_map
;
1687 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1690 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1691 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1692 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1695 buf
->children
.clear();
1700 did_something
= true;
1703 // simplify generate-case blocks
1704 if (type
== AST_GENCASE
&& children
.size() != 0)
1706 AstNode
*buf
= children
[0]->clone();
1707 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1708 if (buf
->type
!= AST_CONSTANT
) {
1709 // for (auto f : log_files)
1710 // dumpAst(f, "verilog-ast> ");
1711 log_file_error(filename
, location
.first_line
, "Condition for generate case is not constant!\n");
1714 bool ref_signed
= buf
->is_signed
;
1715 RTLIL::Const ref_value
= buf
->bitsAsConst();
1718 AstNode
*selected_case
= NULL
;
1719 for (size_t i
= 1; i
< children
.size(); i
++)
1721 log_assert(children
.at(i
)->type
== AST_COND
|| children
.at(i
)->type
== AST_CONDX
|| children
.at(i
)->type
== AST_CONDZ
);
1723 AstNode
*this_genblock
= NULL
;
1724 for (auto child
: children
.at(i
)->children
) {
1725 log_assert(this_genblock
== NULL
);
1726 if (child
->type
== AST_GENBLOCK
)
1727 this_genblock
= child
;
1730 for (auto child
: children
.at(i
)->children
)
1732 if (child
->type
== AST_DEFAULT
) {
1733 if (selected_case
== NULL
)
1734 selected_case
= this_genblock
;
1737 if (child
->type
== AST_GENBLOCK
)
1740 buf
= child
->clone();
1741 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1742 if (buf
->type
!= AST_CONSTANT
) {
1743 // for (auto f : log_files)
1744 // dumpAst(f, "verilog-ast> ");
1745 log_file_error(filename
, location
.first_line
, "Expression in generate case is not constant!\n");
1748 bool is_selected
= RTLIL::const_eq(ref_value
, buf
->bitsAsConst(), ref_signed
&& buf
->is_signed
, ref_signed
&& buf
->is_signed
, 1).as_bool();
1752 selected_case
= this_genblock
;
1753 i
= children
.size();
1759 if (selected_case
!= NULL
)
1761 log_assert(selected_case
->type
== AST_GENBLOCK
);
1762 buf
= selected_case
->clone();
1764 if (!buf
->str
.empty()) {
1765 std::map
<std::string
, std::string
> name_map
;
1766 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1769 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1770 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1771 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1774 buf
->children
.clear();
1779 did_something
= true;
1782 // unroll cell arrays
1783 if (type
== AST_CELLARRAY
)
1785 if (!children
.at(0)->range_valid
)
1786 log_file_error(filename
, location
.first_line
, "Non-constant array range on cell array.\n");
1788 newNode
= new AstNode(AST_GENBLOCK
);
1789 int num
= max(children
.at(0)->range_left
, children
.at(0)->range_right
) - min(children
.at(0)->range_left
, children
.at(0)->range_right
) + 1;
1791 for (int i
= 0; i
< num
; i
++) {
1792 int idx
= children
.at(0)->range_left
> children
.at(0)->range_right
? children
.at(0)->range_right
+ i
: children
.at(0)->range_right
- i
;
1793 AstNode
*new_cell
= children
.at(1)->clone();
1794 newNode
->children
.push_back(new_cell
);
1795 new_cell
->str
+= stringf("[%d]", idx
);
1796 if (new_cell
->type
== AST_PRIMITIVE
) {
1797 log_file_error(filename
, location
.first_line
, "Cell arrays of primitives are currently not supported.\n");
1799 log_assert(new_cell
->children
.at(0)->type
== AST_CELLTYPE
);
1800 new_cell
->children
.at(0)->str
= stringf("$array:%d:%d:%s", i
, num
, new_cell
->children
.at(0)->str
.c_str());
1807 // replace primitives with assignments
1808 if (type
== AST_PRIMITIVE
)
1810 if (children
.size() < 2)
1811 log_file_error(filename
, location
.first_line
, "Insufficient number of arguments for primitive `%s'!\n", str
.c_str());
1813 std::vector
<AstNode
*> children_list
;
1814 for (auto child
: children
) {
1815 log_assert(child
->type
== AST_ARGUMENT
);
1816 log_assert(child
->children
.size() == 1);
1817 children_list
.push_back(child
->children
[0]);
1818 child
->children
.clear();
1823 if (str
== "bufif0" || str
== "bufif1" || str
== "notif0" || str
== "notif1")
1825 if (children_list
.size() != 3)
1826 log_file_error(filename
, location
.first_line
, "Invalid number of arguments for primitive `%s'!\n", str
.c_str());
1828 std::vector
<RTLIL::State
> z_const(1, RTLIL::State::Sz
);
1830 AstNode
*mux_input
= children_list
.at(1);
1831 if (str
== "notif0" || str
== "notif1") {
1832 mux_input
= new AstNode(AST_BIT_NOT
, mux_input
);
1834 AstNode
*node
= new AstNode(AST_TERNARY
, children_list
.at(2));
1835 if (str
== "bufif0") {
1836 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1837 node
->children
.push_back(mux_input
);
1839 node
->children
.push_back(mux_input
);
1840 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1845 children
.push_back(children_list
.at(0));
1846 children
.back()->was_checked
= true;
1847 children
.push_back(node
);
1848 did_something
= true;
1852 AstNodeType op_type
= AST_NONE
;
1853 bool invert_results
= false;
1856 op_type
= AST_BIT_AND
;
1858 op_type
= AST_BIT_AND
, invert_results
= true;
1860 op_type
= AST_BIT_OR
;
1862 op_type
= AST_BIT_OR
, invert_results
= true;
1864 op_type
= AST_BIT_XOR
;
1866 op_type
= AST_BIT_XOR
, invert_results
= true;
1870 op_type
= AST_POS
, invert_results
= true;
1871 log_assert(op_type
!= AST_NONE
);
1873 AstNode
*node
= children_list
[1];
1874 if (op_type
!= AST_POS
)
1875 for (size_t i
= 2; i
< children_list
.size(); i
++) {
1876 node
= new AstNode(op_type
, node
, children_list
[i
]);
1877 node
->location
= location
;
1880 node
= new AstNode(AST_BIT_NOT
, node
);
1884 children
.push_back(children_list
[0]);
1885 children
.back()->was_checked
= true;
1886 children
.push_back(node
);
1887 did_something
= true;
1891 // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
1892 // either a big case block that selects the correct single-bit assignment, or mask and
1893 // shift operations.
1894 if (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
)
1896 if (children
[0]->type
!= AST_IDENTIFIER
|| children
[0]->children
.size() == 0)
1897 goto skip_dynamic_range_lvalue_expansion
;
1898 if (children
[0]->children
[0]->range_valid
|| did_something
)
1899 goto skip_dynamic_range_lvalue_expansion
;
1900 if (children
[0]->id2ast
== NULL
|| children
[0]->id2ast
->type
!= AST_WIRE
)
1901 goto skip_dynamic_range_lvalue_expansion
;
1902 if (!children
[0]->id2ast
->range_valid
)
1903 goto skip_dynamic_range_lvalue_expansion
;
1905 int source_width
= children
[0]->id2ast
->range_left
- children
[0]->id2ast
->range_right
+ 1;
1906 int result_width
= 1;
1908 AstNode
*shift_expr
= NULL
;
1909 AstNode
*range
= children
[0]->children
[0];
1911 if (range
->children
.size() == 1) {
1912 shift_expr
= range
->children
[0]->clone();
1914 shift_expr
= range
->children
[1]->clone();
1915 AstNode
*left_at_zero_ast
= range
->children
[0]->clone();
1916 AstNode
*right_at_zero_ast
= range
->children
[1]->clone();
1917 while (left_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1918 while (right_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1919 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
1920 log_file_error(filename
, location
.first_line
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
1921 result_width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
1924 bool use_case_method
= false;
1926 if (children
[0]->id2ast
->attributes
.count(ID::nowrshmsk
)) {
1927 AstNode
*node
= children
[0]->id2ast
->attributes
.at(ID::nowrshmsk
);
1928 while (node
->simplify(true, false, false, stage
, -1, false, false)) { }
1929 if (node
->type
!= AST_CONSTANT
)
1930 log_file_error(filename
, location
.first_line
, "Non-constant value for `nowrshmsk' attribute on `%s'!\n", children
[0]->id2ast
->str
.c_str());
1931 if (node
->asAttrConst().as_bool())
1932 use_case_method
= true;
1935 if (use_case_method
)
1939 did_something
= true;
1940 newNode
= new AstNode(AST_CASE
, shift_expr
);
1941 for (int i
= 0; i
< source_width
; i
++) {
1942 int start_bit
= children
[0]->id2ast
->range_right
+ i
;
1943 int end_bit
= std::min(start_bit
+result_width
,source_width
) - 1;
1944 AstNode
*cond
= new AstNode(AST_COND
, mkconst_int(start_bit
, true));
1945 AstNode
*lvalue
= children
[0]->clone();
1946 lvalue
->delete_children();
1947 lvalue
->children
.push_back(new AstNode(AST_RANGE
,
1948 mkconst_int(end_bit
, true), mkconst_int(start_bit
, true)));
1949 cond
->children
.push_back(new AstNode(AST_BLOCK
, new AstNode(type
, lvalue
, children
[1]->clone())));
1950 newNode
->children
.push_back(cond
);
1955 // mask and shift operations, disabled for now
1957 AstNode
*wire_mask
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(source_width
-1, true), mkconst_int(0, true)));
1958 wire_mask
->str
= stringf("$bitselwrite$mask$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
1959 wire_mask
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
1960 wire_mask
->is_logic
= true;
1961 while (wire_mask
->simplify(true, false, false, 1, -1, false, false)) { }
1962 current_ast_mod
->children
.push_back(wire_mask
);
1964 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(source_width
-1, true), mkconst_int(0, true)));
1965 wire_data
->str
= stringf("$bitselwrite$data$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
1966 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
1967 wire_data
->is_logic
= true;
1968 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
1969 current_ast_mod
->children
.push_back(wire_data
);
1971 did_something
= true;
1972 newNode
= new AstNode(AST_BLOCK
);
1974 AstNode
*lvalue
= children
[0]->clone();
1975 lvalue
->delete_children();
1977 AstNode
*ref_mask
= new AstNode(AST_IDENTIFIER
);
1978 ref_mask
->str
= wire_mask
->str
;
1979 ref_mask
->id2ast
= wire_mask
;
1980 ref_mask
->was_checked
= true;
1982 AstNode
*ref_data
= new AstNode(AST_IDENTIFIER
);
1983 ref_data
->str
= wire_data
->str
;
1984 ref_data
->id2ast
= wire_data
;
1985 ref_data
->was_checked
= true;
1987 AstNode
*old_data
= lvalue
->clone();
1988 if (type
== AST_ASSIGN_LE
)
1989 old_data
->lookahead
= true;
1991 AstNode
*shamt
= shift_expr
;
1993 int shamt_width_hint
= 0;
1994 bool shamt_sign_hint
= true;
1995 shamt
->detectSignWidth(shamt_width_hint
, shamt_sign_hint
);
1997 int start_bit
= children
[0]->id2ast
->range_right
;
1998 bool use_shift
= shamt_sign_hint
;
2000 if (start_bit
!= 0) {
2001 shamt
= new AstNode(AST_SUB
, shamt
, mkconst_int(start_bit
, true));
2007 t
= mkconst_bits(std::vector
<RTLIL::State
>(result_width
, State::S1
), false);
2009 t
= new AstNode(AST_SHIFT
, t
, new AstNode(AST_NEG
, shamt
->clone()));
2011 t
= new AstNode(AST_SHIFT_LEFT
, t
, shamt
->clone());
2012 t
= new AstNode(AST_ASSIGN_EQ
, ref_mask
->clone(), t
);
2013 newNode
->children
.push_back(t
);
2015 t
= new AstNode(AST_BIT_AND
, mkconst_bits(std::vector
<RTLIL::State
>(result_width
, State::S1
), false), children
[1]->clone());
2017 t
= new AstNode(AST_SHIFT
, t
, new AstNode(AST_NEG
, shamt
));
2019 t
= new AstNode(AST_SHIFT_LEFT
, t
, shamt
);
2020 t
= new AstNode(AST_ASSIGN_EQ
, ref_data
->clone(), t
);
2021 newNode
->children
.push_back(t
);
2023 t
= new AstNode(AST_BIT_AND
, old_data
, new AstNode(AST_BIT_NOT
, ref_mask
));
2024 t
= new AstNode(AST_BIT_OR
, t
, ref_data
);
2025 t
= new AstNode(type
, lvalue
, t
);
2026 newNode
->children
.push_back(t
);
2031 skip_dynamic_range_lvalue_expansion
:;
2033 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && current_block
!= NULL
)
2035 std::stringstream sstr
;
2036 sstr
<< "$formal$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
2037 std::string id_check
= sstr
.str() + "_CHECK", id_en
= sstr
.str() + "_EN";
2039 AstNode
*wire_check
= new AstNode(AST_WIRE
);
2040 wire_check
->str
= id_check
;
2041 wire_check
->was_checked
= true;
2042 current_ast_mod
->children
.push_back(wire_check
);
2043 current_scope
[wire_check
->str
] = wire_check
;
2044 while (wire_check
->simplify(true, false, false, 1, -1, false, false)) { }
2046 AstNode
*wire_en
= new AstNode(AST_WIRE
);
2047 wire_en
->str
= id_en
;
2048 wire_en
->was_checked
= true;
2049 current_ast_mod
->children
.push_back(wire_en
);
2050 if (current_always_clocked
) {
2051 current_ast_mod
->children
.push_back(new AstNode(AST_INITIAL
, new AstNode(AST_BLOCK
, new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), AstNode::mkconst_int(0, false, 1)))));
2052 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->str
= id_en
;
2053 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->was_checked
= true;
2055 current_scope
[wire_en
->str
] = wire_en
;
2056 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
2058 AstNode
*check_defval
;
2059 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
2060 check_defval
= new AstNode(AST_REDUCE_BOOL
, children
[0]->clone());
2062 std::vector
<RTLIL::State
> x_bit
;
2063 x_bit
.push_back(RTLIL::State::Sx
);
2064 check_defval
= mkconst_bits(x_bit
, false);
2067 AstNode
*assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), check_defval
);
2068 assign_check
->children
[0]->str
= id_check
;
2069 assign_check
->children
[0]->was_checked
= true;
2071 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, 1));
2072 assign_en
->children
[0]->str
= id_en
;
2073 assign_en
->children
[0]->was_checked
= true;
2075 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
2076 default_signals
->children
.push_back(assign_check
);
2077 default_signals
->children
.push_back(assign_en
);
2078 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
2080 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
2081 assign_check
= nullptr;
2083 assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_REDUCE_BOOL
, children
[0]->clone()));
2084 assign_check
->children
[0]->str
= id_check
;
2085 assign_check
->children
[0]->was_checked
= true;
2088 if (current_always
== nullptr || current_always
->type
!= AST_INITIAL
) {
2089 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(1, false, 1));
2091 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_FCALL
));
2092 assign_en
->children
[1]->str
= "\\$initstate";
2094 assign_en
->children
[0]->str
= id_en
;
2095 assign_en
->children
[0]->was_checked
= true;
2097 newNode
= new AstNode(AST_BLOCK
);
2098 if (assign_check
!= nullptr)
2099 newNode
->children
.push_back(assign_check
);
2100 newNode
->children
.push_back(assign_en
);
2102 AstNode
*assertnode
= new AstNode(type
);
2103 assertnode
->location
= location
;
2104 assertnode
->str
= str
;
2105 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
2106 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
2107 assertnode
->children
[0]->str
= id_check
;
2108 assertnode
->children
[1]->str
= id_en
;
2109 assertnode
->attributes
.swap(attributes
);
2110 current_ast_mod
->children
.push_back(assertnode
);
2115 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && children
.size() == 1)
2117 children
.push_back(mkconst_int(1, false, 1));
2118 did_something
= true;
2121 // found right-hand side identifier for memory -> replace with memory read port
2122 if (stage
> 1 && type
== AST_IDENTIFIER
&& id2ast
!= NULL
&& id2ast
->type
== AST_MEMORY
&& !in_lvalue
&&
2123 children
.size() == 1 && children
[0]->type
== AST_RANGE
&& children
[0]->children
.size() == 1) {
2124 newNode
= new AstNode(AST_MEMRD
, children
[0]->children
[0]->clone());
2126 newNode
->id2ast
= id2ast
;
2130 // assignment with nontrivial member in left-hand concat expression -> split assignment
2131 if ((type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_CONCAT
&& width_hint
> 0)
2133 bool found_nontrivial_member
= false;
2135 for (auto child
: children
[0]->children
) {
2136 if (child
->type
== AST_IDENTIFIER
&& child
->id2ast
!= NULL
&& child
->id2ast
->type
== AST_MEMORY
)
2137 found_nontrivial_member
= true;
2140 if (found_nontrivial_member
)
2142 newNode
= new AstNode(AST_BLOCK
);
2144 AstNode
*wire_tmp
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
2145 wire_tmp
->str
= stringf("$splitcmplxassign$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
2146 current_ast_mod
->children
.push_back(wire_tmp
);
2147 current_scope
[wire_tmp
->str
] = wire_tmp
;
2148 wire_tmp
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
2149 while (wire_tmp
->simplify(true, false, false, 1, -1, false, false)) { }
2150 wire_tmp
->is_logic
= true;
2152 AstNode
*wire_tmp_id
= new AstNode(AST_IDENTIFIER
);
2153 wire_tmp_id
->str
= wire_tmp
->str
;
2155 newNode
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, wire_tmp_id
, children
[1]->clone()));
2156 newNode
->children
.back()->was_checked
= true;
2159 for (auto child
: children
[0]->children
)
2161 int child_width_hint
= -1;
2162 bool child_sign_hint
= true;
2163 child
->detectSignWidth(child_width_hint
, child_sign_hint
);
2165 AstNode
*rhs
= wire_tmp_id
->clone();
2166 rhs
->children
.push_back(new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+child_width_hint
-1, true), AstNode::mkconst_int(cursor
, true)));
2167 newNode
->children
.push_back(new AstNode(type
, child
->clone(), rhs
));
2169 cursor
+= child_width_hint
;
2176 // assignment with memory in left-hand side expression -> replace with memory write port
2177 if (stage
> 1 && (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_IDENTIFIER
&&
2178 children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
&& children
[0]->id2ast
->children
.size() >= 2 &&
2179 children
[0]->id2ast
->children
[0]->range_valid
&& children
[0]->id2ast
->children
[1]->range_valid
&&
2180 (children
[0]->children
.size() == 1 || children
[0]->children
.size() == 2) && children
[0]->children
[0]->type
== AST_RANGE
)
2182 std::stringstream sstr
;
2183 sstr
<< "$memwr$" << children
[0]->str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
2184 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA", id_en
= sstr
.str() + "_EN";
2186 int mem_width
, mem_size
, addr_bits
;
2187 bool mem_signed
= children
[0]->id2ast
->is_signed
;
2188 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
2190 newNode
= new AstNode(AST_BLOCK
);
2191 AstNode
*defNode
= new AstNode(AST_BLOCK
);
2193 int data_range_left
= children
[0]->id2ast
->children
[0]->range_left
;
2194 int data_range_right
= children
[0]->id2ast
->children
[0]->range_right
;
2195 int mem_data_range_offset
= std::min(data_range_left
, data_range_right
);
2197 int addr_width_hint
= -1;
2198 bool addr_sign_hint
= true;
2199 children
[0]->children
[0]->children
[0]->detectSignWidthWorker(addr_width_hint
, addr_sign_hint
);
2200 addr_bits
= std::max(addr_bits
, addr_width_hint
);
2202 std::vector
<RTLIL::State
> x_bits_addr
, x_bits_data
, set_bits_en
;
2203 for (int i
= 0; i
< addr_bits
; i
++)
2204 x_bits_addr
.push_back(RTLIL::State::Sx
);
2205 for (int i
= 0; i
< mem_width
; i
++)
2206 x_bits_data
.push_back(RTLIL::State::Sx
);
2207 for (int i
= 0; i
< mem_width
; i
++)
2208 set_bits_en
.push_back(RTLIL::State::S1
);
2210 AstNode
*node_addr
= nullptr;
2211 if (children
[0]->children
[0]->children
[0]->isConst()) {
2212 node_addr
= children
[0]->children
[0]->children
[0]->clone();
2214 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
2215 wire_addr
->str
= id_addr
;
2216 wire_addr
->was_checked
= true;
2217 current_ast_mod
->children
.push_back(wire_addr
);
2218 current_scope
[wire_addr
->str
] = wire_addr
;
2219 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
2221 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_addr
, false));
2222 assign_addr
->children
[0]->str
= id_addr
;
2223 assign_addr
->children
[0]->was_checked
= true;
2224 defNode
->children
.push_back(assign_addr
);
2226 assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
2227 assign_addr
->children
[0]->str
= id_addr
;
2228 assign_addr
->children
[0]->was_checked
= true;
2229 newNode
->children
.push_back(assign_addr
);
2231 node_addr
= new AstNode(AST_IDENTIFIER
);
2232 node_addr
->str
= id_addr
;
2235 AstNode
*node_data
= nullptr;
2236 if (children
[0]->children
.size() == 1 && children
[1]->isConst()) {
2237 node_data
= children
[1]->clone();
2239 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
2240 wire_data
->str
= id_data
;
2241 wire_data
->was_checked
= true;
2242 wire_data
->is_signed
= mem_signed
;
2243 current_ast_mod
->children
.push_back(wire_data
);
2244 current_scope
[wire_data
->str
] = wire_data
;
2245 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
2247 AstNode
*assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_data
, false));
2248 assign_data
->children
[0]->str
= id_data
;
2249 assign_data
->children
[0]->was_checked
= true;
2250 defNode
->children
.push_back(assign_data
);
2252 node_data
= new AstNode(AST_IDENTIFIER
);
2253 node_data
->str
= id_data
;
2256 AstNode
*node_en
= nullptr;
2257 if (current_always
->type
== AST_INITIAL
) {
2258 node_en
= AstNode::mkconst_int(1, false);
2260 AstNode
*wire_en
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
2261 wire_en
->str
= id_en
;
2262 wire_en
->was_checked
= true;
2263 current_ast_mod
->children
.push_back(wire_en
);
2264 current_scope
[wire_en
->str
] = wire_en
;
2265 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
2267 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, mem_width
));
2268 assign_en
->children
[0]->str
= id_en
;
2269 assign_en
->children
[0]->was_checked
= true;
2270 defNode
->children
.push_back(assign_en
);
2272 node_en
= new AstNode(AST_IDENTIFIER
);
2273 node_en
->str
= id_en
;
2276 if (!defNode
->children
.empty())
2277 current_top_block
->children
.insert(current_top_block
->children
.begin(), defNode
);
2281 AstNode
*assign_data
= nullptr;
2282 AstNode
*assign_en
= nullptr;
2283 if (children
[0]->children
.size() == 2)
2285 if (children
[0]->children
[1]->range_valid
)
2287 int offset
= children
[0]->children
[1]->range_right
;
2288 int width
= children
[0]->children
[1]->range_left
- offset
+ 1;
2289 offset
-= mem_data_range_offset
;
2291 std::vector
<RTLIL::State
> padding_x(offset
, RTLIL::State::Sx
);
2293 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
2294 new AstNode(AST_CONCAT
, mkconst_bits(padding_x
, false), children
[1]->clone()));
2295 assign_data
->children
[0]->str
= id_data
;
2296 assign_data
->children
[0]->was_checked
= true;
2298 if (current_always
->type
!= AST_INITIAL
) {
2299 for (int i
= 0; i
< mem_width
; i
++)
2300 set_bits_en
[i
] = offset
<= i
&& i
< offset
+width
? RTLIL::State::S1
: RTLIL::State::S0
;
2301 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
2302 assign_en
->children
[0]->str
= id_en
;
2303 assign_en
->children
[0]->was_checked
= true;
2308 AstNode
*the_range
= children
[0]->children
[1];
2309 AstNode
*left_at_zero_ast
= the_range
->children
[0]->clone();
2310 AstNode
*right_at_zero_ast
= the_range
->children
.size() >= 2 ? the_range
->children
[1]->clone() : left_at_zero_ast
->clone();
2311 AstNode
*offset_ast
= right_at_zero_ast
->clone();
2313 if (mem_data_range_offset
)
2314 offset_ast
= new AstNode(AST_SUB
, offset_ast
, mkconst_int(mem_data_range_offset
, true));
2316 while (left_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
2317 while (right_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
2318 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
2319 log_file_error(filename
, location
.first_line
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
2320 int width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
2322 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
2323 new AstNode(AST_SHIFT_LEFT
, children
[1]->clone(), offset_ast
->clone()));
2324 assign_data
->children
[0]->str
= id_data
;
2325 assign_data
->children
[0]->was_checked
= true;
2327 if (current_always
->type
!= AST_INITIAL
) {
2328 for (int i
= 0; i
< mem_width
; i
++)
2329 set_bits_en
[i
] = i
< width
? RTLIL::State::S1
: RTLIL::State::S0
;
2330 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
2331 new AstNode(AST_SHIFT_LEFT
, mkconst_bits(set_bits_en
, false), offset_ast
->clone()));
2332 assign_en
->children
[0]->str
= id_en
;
2333 assign_en
->children
[0]->was_checked
= true;
2336 delete left_at_zero_ast
;
2337 delete right_at_zero_ast
;
2343 if (!(children
[0]->children
.size() == 1 && children
[1]->isConst())) {
2344 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[1]->clone());
2345 assign_data
->children
[0]->str
= id_data
;
2346 assign_data
->children
[0]->was_checked
= true;
2349 if (current_always
->type
!= AST_INITIAL
) {
2350 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
2351 assign_en
->children
[0]->str
= id_en
;
2352 assign_en
->children
[0]->was_checked
= true;
2356 newNode
->children
.push_back(assign_data
);
2358 newNode
->children
.push_back(assign_en
);
2360 AstNode
*wrnode
= new AstNode(current_always
->type
== AST_INITIAL
? AST_MEMINIT
: AST_MEMWR
, node_addr
, node_data
, node_en
);
2361 wrnode
->str
= children
[0]->str
;
2362 wrnode
->id2ast
= children
[0]->id2ast
;
2363 current_ast_mod
->children
.push_back(wrnode
);
2365 if (newNode
->children
.empty()) {
2367 newNode
= new AstNode();
2372 // replace function and task calls with the code from the function or task
2373 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && !str
.empty())
2375 if (type
== AST_FCALL
)
2377 if (str
== "\\$initstate")
2379 int myidx
= autoidx
++;
2381 AstNode
*wire
= new AstNode(AST_WIRE
);
2382 wire
->str
= stringf("$initstate$%d_wire", myidx
);
2383 current_ast_mod
->children
.push_back(wire
);
2384 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2386 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
), new AstNode(AST_ARGUMENT
, new AstNode(AST_IDENTIFIER
)));
2387 cell
->str
= stringf("$initstate$%d", myidx
);
2388 cell
->children
[0]->str
= "$initstate";
2389 cell
->children
[1]->str
= "\\Y";
2390 cell
->children
[1]->children
[0]->str
= wire
->str
;
2391 cell
->children
[1]->children
[0]->id2ast
= wire
;
2392 current_ast_mod
->children
.push_back(cell
);
2393 while (cell
->simplify(true, false, false, 1, -1, false, false)) { }
2395 newNode
= new AstNode(AST_IDENTIFIER
);
2396 newNode
->str
= wire
->str
;
2397 newNode
->id2ast
= wire
;
2401 if (str
== "\\$past")
2404 goto replace_fcall_later
;
2408 if (GetSize(children
) != 1 && GetSize(children
) != 2)
2409 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1 or 2.\n",
2410 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2412 if (!current_always_clocked
)
2413 log_file_error(filename
, location
.first_line
, "System function %s is only allowed in clocked blocks.\n",
2414 RTLIL::unescape_id(str
).c_str());
2416 if (GetSize(children
) == 2)
2418 AstNode
*buf
= children
[1]->clone();
2419 while (buf
->simplify(true, false, false, stage
, -1, false, false)) { }
2420 if (buf
->type
!= AST_CONSTANT
)
2421 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
2423 num_steps
= buf
->asInt(true);
2427 AstNode
*block
= nullptr;
2429 for (auto child
: current_always
->children
)
2430 if (child
->type
== AST_BLOCK
)
2433 log_assert(block
!= nullptr);
2435 if (num_steps
== 0) {
2436 newNode
= children
[0]->clone();
2440 int myidx
= autoidx
++;
2441 AstNode
*outreg
= nullptr;
2443 for (int i
= 0; i
< num_steps
; i
++)
2445 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
2446 mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
2448 reg
->str
= stringf("$past$%s:%d$%d$%d", filename
.c_str(), location
.first_line
, myidx
, i
);
2451 current_ast_mod
->children
.push_back(reg
);
2453 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
2455 AstNode
*regid
= new AstNode(AST_IDENTIFIER
);
2456 regid
->str
= reg
->str
;
2457 regid
->id2ast
= reg
;
2458 regid
->was_checked
= true;
2460 AstNode
*rhs
= nullptr;
2462 if (outreg
== nullptr) {
2463 rhs
= children
.at(0)->clone();
2465 rhs
= new AstNode(AST_IDENTIFIER
);
2466 rhs
->str
= outreg
->str
;
2467 rhs
->id2ast
= outreg
;
2470 block
->children
.push_back(new AstNode(AST_ASSIGN_LE
, regid
, rhs
));
2474 newNode
= new AstNode(AST_IDENTIFIER
);
2475 newNode
->str
= outreg
->str
;
2476 newNode
->id2ast
= outreg
;
2480 if (str
== "\\$stable" || str
== "\\$rose" || str
== "\\$fell" || str
== "\\$changed")
2482 if (GetSize(children
) != 1)
2483 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2484 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2486 if (!current_always_clocked
)
2487 log_file_error(filename
, location
.first_line
, "System function %s is only allowed in clocked blocks.\n",
2488 RTLIL::unescape_id(str
).c_str());
2490 AstNode
*present
= children
.at(0)->clone();
2491 AstNode
*past
= clone();
2492 past
->str
= "\\$past";
2494 if (str
== "\\$stable")
2495 newNode
= new AstNode(AST_EQ
, past
, present
);
2497 else if (str
== "\\$changed")
2498 newNode
= new AstNode(AST_NE
, past
, present
);
2500 else if (str
== "\\$rose")
2501 newNode
= new AstNode(AST_LOGIC_AND
,
2502 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false))),
2503 new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false)));
2505 else if (str
== "\\$fell")
2506 newNode
= new AstNode(AST_LOGIC_AND
,
2507 new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false)),
2508 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false))));
2516 // $anyconst and $anyseq are mapped in AstNode::genRTLIL()
2517 if (str
== "\\$anyconst" || str
== "\\$anyseq" || str
== "\\$allconst" || str
== "\\$allseq") {
2518 recursion_counter
--;
2522 if (str
== "\\$clog2")
2524 if (children
.size() != 1)
2525 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2526 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2528 AstNode
*buf
= children
[0]->clone();
2529 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2530 if (buf
->type
!= AST_CONSTANT
)
2531 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
2533 RTLIL::Const arg_value
= buf
->bitsAsConst();
2534 if (arg_value
.as_bool())
2535 arg_value
= const_sub(arg_value
, 1, false, false, GetSize(arg_value
));
2538 uint32_t result
= 0;
2539 for (size_t i
= 0; i
< arg_value
.bits
.size(); i
++)
2540 if (arg_value
.bits
.at(i
) == RTLIL::State::S1
)
2543 newNode
= mkconst_int(result
, true);
2547 if (str
== "\\$size" || str
== "\\$bits")
2549 if (str
== "\\$bits" && children
.size() != 1)
2550 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2551 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2553 if (str
== "\\$size" && children
.size() != 1 && children
.size() != 2)
2554 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1 or 2.\n",
2555 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2558 if (str
== "\\$size" && children
.size() == 2) {
2559 AstNode
*buf
= children
[1]->clone();
2560 // Evaluate constant expression
2561 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2562 dim
= buf
->asInt(false);
2565 AstNode
*buf
= children
[0]->clone();
2567 AstNode
*id_ast
= NULL
;
2570 //while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2571 buf
->detectSignWidth(width_hint
, sign_hint
);
2573 if (buf
->type
== AST_IDENTIFIER
) {
2574 id_ast
= buf
->id2ast
;
2575 if (id_ast
== NULL
&& current_scope
.count(buf
->str
))
2576 id_ast
= current_scope
.at(buf
->str
);
2578 log_file_error(filename
, location
.first_line
, "Failed to resolve identifier %s for width detection!\n", buf
->str
.c_str());
2579 if (id_ast
->type
== AST_MEMORY
) {
2580 // We got here only if the argument is a memory
2581 // Otherwise $size() and $bits() return the expression width
2582 AstNode
*mem_range
= id_ast
->children
[1];
2583 if (str
== "\\$bits") {
2584 if (mem_range
->type
== AST_RANGE
) {
2585 if (!mem_range
->range_valid
)
2586 log_file_error(filename
, location
.first_line
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2587 mem_depth
= mem_range
->range_left
- mem_range
->range_right
+ 1;
2589 log_file_error(filename
, location
.first_line
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2592 if (mem_range
->type
== AST_RANGE
) {
2593 if (!mem_range
->range_valid
)
2594 log_file_error(filename
, location
.first_line
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2596 if (id_ast
->multirange_dimensions
.empty())
2599 dims
= GetSize(id_ast
->multirange_dimensions
)/2;
2601 width_hint
= (dims
> 1) ? id_ast
->multirange_dimensions
[1] : (mem_range
->range_left
- mem_range
->range_right
+ 1);
2602 else if (dim
<= dims
) {
2603 width_hint
= id_ast
->multirange_dimensions
[2*dim
-1];
2604 } else if ((dim
> dims
+1) || (dim
< 0))
2605 log_file_error(filename
, location
.first_line
, "Dimension %d out of range in `%s', as it only has dimensions 1..%d!\n", dim
, buf
->str
.c_str(), dims
+1);
2607 log_file_error(filename
, location
.first_line
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2613 newNode
= mkconst_int(width_hint
* mem_depth
, false);
2617 if (str
== "\\$ln" || str
== "\\$log10" || str
== "\\$exp" || str
== "\\$sqrt" || str
== "\\$pow" ||
2618 str
== "\\$floor" || str
== "\\$ceil" || str
== "\\$sin" || str
== "\\$cos" || str
== "\\$tan" ||
2619 str
== "\\$asin" || str
== "\\$acos" || str
== "\\$atan" || str
== "\\$atan2" || str
== "\\$hypot" ||
2620 str
== "\\$sinh" || str
== "\\$cosh" || str
== "\\$tanh" || str
== "\\$asinh" || str
== "\\$acosh" || str
== "\\$atanh" ||
2621 str
== "\\$rtoi" || str
== "\\$itor")
2623 bool func_with_two_arguments
= str
== "\\$pow" || str
== "\\$atan2" || str
== "\\$hypot";
2624 double x
= 0, y
= 0;
2626 if (func_with_two_arguments
) {
2627 if (children
.size() != 2)
2628 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 2.\n",
2629 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2631 if (children
.size() != 1)
2632 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2633 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2636 if (children
.size() >= 1) {
2637 while (children
[0]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2638 if (!children
[0]->isConst())
2639 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant argument.\n",
2640 RTLIL::unescape_id(str
).c_str());
2641 int child_width_hint
= width_hint
;
2642 bool child_sign_hint
= sign_hint
;
2643 children
[0]->detectSignWidth(child_width_hint
, child_sign_hint
);
2644 x
= children
[0]->asReal(child_sign_hint
);
2647 if (children
.size() >= 2) {
2648 while (children
[1]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2649 if (!children
[1]->isConst())
2650 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant argument.\n",
2651 RTLIL::unescape_id(str
).c_str());
2652 int child_width_hint
= width_hint
;
2653 bool child_sign_hint
= sign_hint
;
2654 children
[1]->detectSignWidth(child_width_hint
, child_sign_hint
);
2655 y
= children
[1]->asReal(child_sign_hint
);
2658 if (str
== "\\$rtoi") {
2659 newNode
= AstNode::mkconst_int(x
, true);
2661 newNode
= new AstNode(AST_REALVALUE
);
2662 if (str
== "\\$ln") newNode
->realvalue
= ::log(x
);
2663 else if (str
== "\\$log10") newNode
->realvalue
= ::log10(x
);
2664 else if (str
== "\\$exp") newNode
->realvalue
= ::exp(x
);
2665 else if (str
== "\\$sqrt") newNode
->realvalue
= ::sqrt(x
);
2666 else if (str
== "\\$pow") newNode
->realvalue
= ::pow(x
, y
);
2667 else if (str
== "\\$floor") newNode
->realvalue
= ::floor(x
);
2668 else if (str
== "\\$ceil") newNode
->realvalue
= ::ceil(x
);
2669 else if (str
== "\\$sin") newNode
->realvalue
= ::sin(x
);
2670 else if (str
== "\\$cos") newNode
->realvalue
= ::cos(x
);
2671 else if (str
== "\\$tan") newNode
->realvalue
= ::tan(x
);
2672 else if (str
== "\\$asin") newNode
->realvalue
= ::asin(x
);
2673 else if (str
== "\\$acos") newNode
->realvalue
= ::acos(x
);
2674 else if (str
== "\\$atan") newNode
->realvalue
= ::atan(x
);
2675 else if (str
== "\\$atan2") newNode
->realvalue
= ::atan2(x
, y
);
2676 else if (str
== "\\$hypot") newNode
->realvalue
= ::hypot(x
, y
);
2677 else if (str
== "\\$sinh") newNode
->realvalue
= ::sinh(x
);
2678 else if (str
== "\\$cosh") newNode
->realvalue
= ::cosh(x
);
2679 else if (str
== "\\$tanh") newNode
->realvalue
= ::tanh(x
);
2680 else if (str
== "\\$asinh") newNode
->realvalue
= ::asinh(x
);
2681 else if (str
== "\\$acosh") newNode
->realvalue
= ::acosh(x
);
2682 else if (str
== "\\$atanh") newNode
->realvalue
= ::atanh(x
);
2683 else if (str
== "\\$itor") newNode
->realvalue
= x
;
2689 if (str
== "\\$sformatf") {
2690 AstNode
*node_string
= children
[0];
2691 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2692 if (node_string
->type
!= AST_CONSTANT
)
2693 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
2694 std::string sformat
= node_string
->bitsAsConst().decode_string();
2695 std::string sout
= process_format_str(sformat
, 1, stage
, width_hint
, sign_hint
);
2696 newNode
= AstNode::mkconst_str(sout
);
2700 if (current_scope
.count(str
) != 0 && current_scope
[str
]->type
== AST_DPI_FUNCTION
)
2702 AstNode
*dpi_decl
= current_scope
[str
];
2704 std::string rtype
, fname
;
2705 std::vector
<std::string
> argtypes
;
2706 std::vector
<AstNode
*> args
;
2708 rtype
= RTLIL::unescape_id(dpi_decl
->children
.at(0)->str
);
2709 fname
= RTLIL::unescape_id(dpi_decl
->children
.at(1)->str
);
2711 for (int i
= 2; i
< GetSize(dpi_decl
->children
); i
++)
2713 if (i
-2 >= GetSize(children
))
2714 log_file_error(filename
, location
.first_line
, "Insufficient number of arguments in DPI function call.\n");
2716 argtypes
.push_back(RTLIL::unescape_id(dpi_decl
->children
.at(i
)->str
));
2717 args
.push_back(children
.at(i
-2)->clone());
2718 while (args
.back()->simplify(true, false, false, stage
, -1, false, true)) { }
2720 if (args
.back()->type
!= AST_CONSTANT
&& args
.back()->type
!= AST_REALVALUE
)
2721 log_file_error(filename
, location
.first_line
, "Failed to evaluate DPI function with non-constant argument.\n");
2724 newNode
= dpi_call(rtype
, fname
, argtypes
, args
);
2726 for (auto arg
: args
)
2732 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_FUNCTION
)
2733 log_file_error(filename
, location
.first_line
, "Can't resolve function name `%s'.\n", str
.c_str());
2736 if (type
== AST_TCALL
)
2738 if (str
== "$finish" || str
== "$stop")
2740 if (!current_always
|| current_always
->type
!= AST_INITIAL
)
2741 log_file_error(filename
, location
.first_line
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
2743 log_file_error(filename
, location
.first_line
, "System task `%s' executed.\n", str
.c_str());
2746 if (str
== "\\$readmemh" || str
== "\\$readmemb")
2748 if (GetSize(children
) < 2 || GetSize(children
) > 4)
2749 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 2-4.\n",
2750 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2752 AstNode
*node_filename
= children
[0]->clone();
2753 while (node_filename
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2754 if (node_filename
->type
!= AST_CONSTANT
)
2755 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
2757 AstNode
*node_memory
= children
[1]->clone();
2758 while (node_memory
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2759 if (node_memory
->type
!= AST_IDENTIFIER
|| node_memory
->id2ast
== nullptr || node_memory
->id2ast
->type
!= AST_MEMORY
)
2760 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str
.c_str());
2762 int start_addr
= -1, finish_addr
= -1;
2764 if (GetSize(children
) > 2) {
2765 AstNode
*node_addr
= children
[2]->clone();
2766 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2767 if (node_addr
->type
!= AST_CONSTANT
)
2768 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str
.c_str());
2769 start_addr
= int(node_addr
->asInt(false));
2772 if (GetSize(children
) > 3) {
2773 AstNode
*node_addr
= children
[3]->clone();
2774 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2775 if (node_addr
->type
!= AST_CONSTANT
)
2776 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str
.c_str());
2777 finish_addr
= int(node_addr
->asInt(false));
2780 bool unconditional_init
= false;
2781 if (current_always
->type
== AST_INITIAL
) {
2782 pool
<AstNode
*> queue
;
2783 log_assert(current_always
->children
[0]->type
== AST_BLOCK
);
2784 queue
.insert(current_always
->children
[0]);
2785 while (!unconditional_init
&& !queue
.empty()) {
2786 pool
<AstNode
*> next_queue
;
2787 for (auto n
: queue
)
2788 for (auto c
: n
->children
) {
2790 unconditional_init
= true;
2791 next_queue
.insert(c
);
2793 next_queue
.swap(queue
);
2797 newNode
= readmem(str
== "\\$readmemh", node_filename
->bitsAsConst().decode_string(), node_memory
->id2ast
, start_addr
, finish_addr
, unconditional_init
);
2798 delete node_filename
;
2803 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_TASK
)
2804 log_file_error(filename
, location
.first_line
, "Can't resolve task name `%s'.\n", str
.c_str());
2807 AstNode
*decl
= current_scope
[str
];
2809 std::stringstream sstr
;
2810 sstr
<< "$func$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++) << "$";
2811 std::string prefix
= sstr
.str();
2813 bool recommend_const_eval
= false;
2814 bool require_const_eval
= in_param
? false : has_const_only_constructs(recommend_const_eval
);
2815 if ((in_param
|| recommend_const_eval
|| require_const_eval
) && !decl
->attributes
.count(ID::via_celltype
))
2817 bool all_args_const
= true;
2818 for (auto child
: children
) {
2819 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
2820 if (child
->type
!= AST_CONSTANT
)
2821 all_args_const
= false;
2824 if (all_args_const
) {
2825 AstNode
*func_workspace
= current_scope
[str
]->clone();
2826 newNode
= func_workspace
->eval_const_function(this);
2827 delete func_workspace
;
2832 log_file_error(filename
, location
.first_line
, "Non-constant function call in constant expression.\n");
2833 if (require_const_eval
)
2834 log_file_error(filename
, location
.first_line
, "Function %s can only be called with constant arguments.\n", str
.c_str());
2837 size_t arg_count
= 0;
2838 std::map
<std::string
, std::string
> replace_rules
;
2839 vector
<AstNode
*> added_mod_children
;
2840 dict
<std::string
, AstNode
*> wire_cache
;
2841 vector
<AstNode
*> new_stmts
;
2842 vector
<AstNode
*> output_assignments
;
2844 if (current_block
== NULL
)
2846 log_assert(type
== AST_FCALL
);
2848 AstNode
*wire
= NULL
;
2849 for (auto child
: decl
->children
)
2850 if (child
->type
== AST_WIRE
&& child
->str
== str
)
2851 wire
= child
->clone();
2852 log_assert(wire
!= NULL
);
2854 wire
->str
= prefix
+ str
;
2856 wire
->is_input
= false;
2857 wire
->is_output
= false;
2859 current_ast_mod
->children
.push_back(wire
);
2860 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2862 AstNode
*lvalue
= new AstNode(AST_IDENTIFIER
);
2863 lvalue
->str
= wire
->str
;
2865 AstNode
*always
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
,
2866 new AstNode(AST_ASSIGN_EQ
, lvalue
, clone())));
2867 always
->children
[0]->children
[0]->was_checked
= true;
2869 current_ast_mod
->children
.push_back(always
);
2871 goto replace_fcall_with_id
;
2874 if (decl
->attributes
.count(ID::via_celltype
))
2876 std::string celltype
= decl
->attributes
.at(ID::via_celltype
)->asAttrConst().decode_string();
2877 std::string outport
= str
;
2879 if (celltype
.find(' ') != std::string::npos
) {
2880 int pos
= celltype
.find(' ');
2881 outport
= RTLIL::escape_id(celltype
.substr(pos
+1));
2882 celltype
= RTLIL::escape_id(celltype
.substr(0, pos
));
2884 celltype
= RTLIL::escape_id(celltype
);
2886 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
));
2887 cell
->str
= prefix
.substr(0, GetSize(prefix
)-1);
2888 cell
->children
[0]->str
= celltype
;
2890 for (auto attr
: decl
->attributes
)
2891 if (attr
.first
.str().rfind("\\via_celltype_defparam_", 0) == 0)
2893 AstNode
*cell_arg
= new AstNode(AST_PARASET
, attr
.second
->clone());
2894 cell_arg
->str
= RTLIL::escape_id(attr
.first
.substr(strlen("\\via_celltype_defparam_")));
2895 cell
->children
.push_back(cell_arg
);
2898 for (auto child
: decl
->children
)
2899 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
|| (type
== AST_FCALL
&& child
->str
== str
)))
2901 AstNode
*wire
= child
->clone();
2902 wire
->str
= prefix
+ wire
->str
;
2904 wire
->is_input
= false;
2905 wire
->is_output
= false;
2906 current_ast_mod
->children
.push_back(wire
);
2907 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2909 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
2910 wire_id
->str
= wire
->str
;
2912 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
2914 AstNode
*arg
= children
[arg_count
++]->clone();
2915 AstNode
*assign
= child
->is_input
?
2916 new AstNode(AST_ASSIGN_EQ
, wire_id
->clone(), arg
) :
2917 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
->clone());
2918 assign
->children
[0]->was_checked
= true;
2920 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
2921 if (*it
!= current_block_child
)
2923 current_block
->children
.insert(it
, assign
);
2928 AstNode
*cell_arg
= new AstNode(AST_ARGUMENT
, wire_id
);
2929 cell_arg
->str
= child
->str
== str
? outport
: child
->str
;
2930 cell
->children
.push_back(cell_arg
);
2933 current_ast_mod
->children
.push_back(cell
);
2934 goto replace_fcall_with_id
;
2937 for (auto child
: decl
->children
)
2938 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
|| child
->type
== AST_ENUM_ITEM
)
2940 AstNode
*wire
= nullptr;
2942 if (wire_cache
.count(child
->str
))
2944 wire
= wire_cache
.at(child
->str
);
2945 if (wire
->children
.empty()) {
2946 for (auto c
: child
->children
)
2947 wire
->children
.push_back(c
->clone());
2948 } else if (!child
->children
.empty()) {
2949 while (child
->simplify(true, false, false, stage
, -1, false, false)) { }
2950 if (GetSize(child
->children
) == GetSize(wire
->children
)) {
2951 for (int i
= 0; i
< GetSize(child
->children
); i
++)
2952 if (*child
->children
.at(i
) != *wire
->children
.at(i
))
2953 goto tcall_incompatible_wires
;
2955 tcall_incompatible_wires
:
2956 log_file_error(filename
, location
.first_line
, "Incompatible re-declaration of wire %s.\n", child
->str
.c_str());
2962 wire
= child
->clone();
2963 wire
->str
= prefix
+ wire
->str
;
2965 wire
->is_input
= false;
2966 wire
->is_output
= false;
2967 wire
->is_reg
= true;
2968 wire
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
2969 if (child
->type
== AST_ENUM_ITEM
)
2970 wire
->attributes
[ID::enum_base_type
] = child
->attributes
[ID::enum_base_type
];
2972 wire_cache
[child
->str
] = wire
;
2974 current_ast_mod
->children
.push_back(wire
);
2975 added_mod_children
.push_back(wire
);
2978 if (child
->type
== AST_WIRE
)
2979 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2981 replace_rules
[child
->str
] = wire
->str
;
2982 current_scope
[wire
->str
] = wire
;
2984 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
2986 AstNode
*arg
= children
[arg_count
++]->clone();
2987 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
2988 wire_id
->str
= wire
->str
;
2989 AstNode
*assign
= child
->is_input
?
2990 new AstNode(AST_ASSIGN_EQ
, wire_id
, arg
) :
2991 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
);
2992 assign
->children
[0]->was_checked
= true;
2993 if (child
->is_input
)
2994 new_stmts
.push_back(assign
);
2996 output_assignments
.push_back(assign
);
3000 for (auto child
: added_mod_children
) {
3001 child
->replace_ids(prefix
, replace_rules
);
3002 while (child
->simplify(true, false, false, 1, -1, false, false)) { }
3005 for (auto child
: decl
->children
)
3006 if (child
->type
!= AST_WIRE
&& child
->type
!= AST_MEMORY
&& child
->type
!= AST_PARAMETER
&& child
->type
!= AST_LOCALPARAM
)
3008 AstNode
*stmt
= child
->clone();
3009 stmt
->replace_ids(prefix
, replace_rules
);
3010 new_stmts
.push_back(stmt
);
3013 new_stmts
.insert(new_stmts
.end(), output_assignments
.begin(), output_assignments
.end());
3015 for (auto it
= current_block
->children
.begin(); ; it
++) {
3016 log_assert(it
!= current_block
->children
.end());
3017 if (*it
== current_block_child
) {
3018 current_block
->children
.insert(it
, new_stmts
.begin(), new_stmts
.end());
3023 replace_fcall_with_id
:
3024 if (type
== AST_FCALL
) {
3026 type
= AST_IDENTIFIER
;
3029 if (type
== AST_TCALL
)
3031 did_something
= true;
3034 replace_fcall_later
:;
3036 // perform const folding when activated
3040 std::vector
<RTLIL::State
> tmp_bits
;
3041 RTLIL::Const (*const_func
)(const RTLIL::Const
&, const RTLIL::Const
&, bool, bool, int);
3042 RTLIL::Const dummy_arg
;
3046 case AST_IDENTIFIER
:
3047 if (current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
|| current_scope
[str
]->type
== AST_ENUM_ITEM
)) {
3048 if (current_scope
[str
]->children
[0]->type
== AST_CONSTANT
) {
3049 if (children
.size() != 0 && children
[0]->type
== AST_RANGE
&& children
[0]->range_valid
) {
3050 std::vector
<RTLIL::State
> data
;
3051 bool param_upto
= current_scope
[str
]->range_valid
&& current_scope
[str
]->range_swapped
;
3052 int param_offset
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_right
: 0;
3053 int param_width
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_left
- current_scope
[str
]->range_right
+ 1 :
3054 GetSize(current_scope
[str
]->children
[0]->bits
);
3055 int tmp_range_left
= children
[0]->range_left
, tmp_range_right
= children
[0]->range_right
;
3057 tmp_range_left
= (param_width
+ 2*param_offset
) - children
[0]->range_right
- 1;
3058 tmp_range_right
= (param_width
+ 2*param_offset
) - children
[0]->range_left
- 1;
3060 for (int i
= tmp_range_right
; i
<= tmp_range_left
; i
++) {
3061 int index
= i
- param_offset
;
3062 if (0 <= index
&& index
< param_width
)
3063 data
.push_back(current_scope
[str
]->children
[0]->bits
[index
]);
3065 data
.push_back(RTLIL::State::Sx
);
3067 newNode
= mkconst_bits(data
, false);
3069 if (children
.size() == 0)
3070 newNode
= current_scope
[str
]->children
[0]->clone();
3072 if (current_scope
[str
]->children
[0]->isConst())
3073 newNode
= current_scope
[str
]->children
[0]->clone();
3075 else if (at_zero
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_WIRE
|| current_scope
[str
]->type
== AST_AUTOWIRE
)) {
3076 newNode
= mkconst_int(0, sign_hint
, width_hint
);
3080 if (children
[0]->type
== AST_CONSTANT
) {
3081 RTLIL::Const y
= RTLIL::const_not(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
3082 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3086 case AST_TO_UNSIGNED
:
3087 if (children
[0]->type
== AST_CONSTANT
) {
3088 RTLIL::Const y
= children
[0]->bitsAsConst(width_hint
, sign_hint
);
3089 newNode
= mkconst_bits(y
.bits
, type
== AST_TO_SIGNED
);
3092 if (0) { case AST_BIT_AND
: const_func
= RTLIL::const_and
; }
3093 if (0) { case AST_BIT_OR
: const_func
= RTLIL::const_or
; }
3094 if (0) { case AST_BIT_XOR
: const_func
= RTLIL::const_xor
; }
3095 if (0) { case AST_BIT_XNOR
: const_func
= RTLIL::const_xnor
; }
3096 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3097 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3098 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
3099 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3102 if (0) { case AST_REDUCE_AND
: const_func
= RTLIL::const_reduce_and
; }
3103 if (0) { case AST_REDUCE_OR
: const_func
= RTLIL::const_reduce_or
; }
3104 if (0) { case AST_REDUCE_XOR
: const_func
= RTLIL::const_reduce_xor
; }
3105 if (0) { case AST_REDUCE_XNOR
: const_func
= RTLIL::const_reduce_xnor
; }
3106 if (0) { case AST_REDUCE_BOOL
: const_func
= RTLIL::const_reduce_bool
; }
3107 if (children
[0]->type
== AST_CONSTANT
) {
3108 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), dummy_arg
, false, false, -1);
3109 newNode
= mkconst_bits(y
.bits
, false);
3113 if (children
[0]->type
== AST_CONSTANT
) {
3114 RTLIL::Const y
= RTLIL::const_logic_not(RTLIL::Const(children
[0]->bits
), dummy_arg
, children
[0]->is_signed
, false, -1);
3115 newNode
= mkconst_bits(y
.bits
, false);
3117 if (children
[0]->isConst()) {
3118 newNode
= mkconst_int(children
[0]->asReal(sign_hint
) == 0, false, 1);
3121 if (0) { case AST_LOGIC_AND
: const_func
= RTLIL::const_logic_and
; }
3122 if (0) { case AST_LOGIC_OR
: const_func
= RTLIL::const_logic_or
; }
3123 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3124 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), RTLIL::Const(children
[1]->bits
),
3125 children
[0]->is_signed
, children
[1]->is_signed
, -1);
3126 newNode
= mkconst_bits(y
.bits
, false);
3128 if (children
[0]->isConst() && children
[1]->isConst()) {
3129 if (type
== AST_LOGIC_AND
)
3130 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) && (children
[1]->asReal(sign_hint
) != 0), false, 1);
3132 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) || (children
[1]->asReal(sign_hint
) != 0), false, 1);
3135 if (0) { case AST_SHIFT_LEFT
: const_func
= RTLIL::const_shl
; }
3136 if (0) { case AST_SHIFT_RIGHT
: const_func
= RTLIL::const_shr
; }
3137 if (0) { case AST_SHIFT_SLEFT
: const_func
= RTLIL::const_sshl
; }
3138 if (0) { case AST_SHIFT_SRIGHT
: const_func
= RTLIL::const_sshr
; }
3139 if (0) { case AST_POW
: const_func
= RTLIL::const_pow
; }
3140 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3141 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3142 RTLIL::Const(children
[1]->bits
), sign_hint
, type
== AST_POW
? children
[1]->is_signed
: false, width_hint
);
3143 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3145 if (type
== AST_POW
&& children
[0]->isConst() && children
[1]->isConst()) {
3146 newNode
= new AstNode(AST_REALVALUE
);
3147 newNode
->realvalue
= pow(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
));
3150 if (0) { case AST_LT
: const_func
= RTLIL::const_lt
; }
3151 if (0) { case AST_LE
: const_func
= RTLIL::const_le
; }
3152 if (0) { case AST_EQ
: const_func
= RTLIL::const_eq
; }
3153 if (0) { case AST_NE
: const_func
= RTLIL::const_ne
; }
3154 if (0) { case AST_EQX
: const_func
= RTLIL::const_eqx
; }
3155 if (0) { case AST_NEX
: const_func
= RTLIL::const_nex
; }
3156 if (0) { case AST_GE
: const_func
= RTLIL::const_ge
; }
3157 if (0) { case AST_GT
: const_func
= RTLIL::const_gt
; }
3158 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3159 int cmp_width
= max(children
[0]->bits
.size(), children
[1]->bits
.size());
3160 bool cmp_signed
= children
[0]->is_signed
&& children
[1]->is_signed
;
3161 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(cmp_width
, cmp_signed
),
3162 children
[1]->bitsAsConst(cmp_width
, cmp_signed
), cmp_signed
, cmp_signed
, 1);
3163 newNode
= mkconst_bits(y
.bits
, false);
3165 if (children
[0]->isConst() && children
[1]->isConst()) {
3166 bool cmp_signed
= (children
[0]->type
== AST_REALVALUE
|| children
[0]->is_signed
) && (children
[1]->type
== AST_REALVALUE
|| children
[1]->is_signed
);
3168 case AST_LT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) < children
[1]->asReal(cmp_signed
), false, 1); break;
3169 case AST_LE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) <= children
[1]->asReal(cmp_signed
), false, 1); break;
3170 case AST_EQ
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
3171 case AST_NE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
3172 case AST_EQX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
3173 case AST_NEX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
3174 case AST_GE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) >= children
[1]->asReal(cmp_signed
), false, 1); break;
3175 case AST_GT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) > children
[1]->asReal(cmp_signed
), false, 1); break;
3176 default: log_abort();
3180 if (0) { case AST_ADD
: const_func
= RTLIL::const_add
; }
3181 if (0) { case AST_SUB
: const_func
= RTLIL::const_sub
; }
3182 if (0) { case AST_MUL
: const_func
= RTLIL::const_mul
; }
3183 if (0) { case AST_DIV
: const_func
= RTLIL::const_div
; }
3184 if (0) { case AST_MOD
: const_func
= RTLIL::const_mod
; }
3185 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3186 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3187 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
3188 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3190 if (children
[0]->isConst() && children
[1]->isConst()) {
3191 newNode
= new AstNode(AST_REALVALUE
);
3193 case AST_ADD
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) + children
[1]->asReal(sign_hint
); break;
3194 case AST_SUB
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) - children
[1]->asReal(sign_hint
); break;
3195 case AST_MUL
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) * children
[1]->asReal(sign_hint
); break;
3196 case AST_DIV
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) / children
[1]->asReal(sign_hint
); break;
3197 case AST_MOD
: newNode
->realvalue
= fmod(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
)); break;
3198 default: log_abort();
3202 if (0) { case AST_SELFSZ
: const_func
= RTLIL::const_pos
; }
3203 if (0) { case AST_POS
: const_func
= RTLIL::const_pos
; }
3204 if (0) { case AST_NEG
: const_func
= RTLIL::const_neg
; }
3205 if (children
[0]->type
== AST_CONSTANT
) {
3206 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
3207 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3209 if (children
[0]->isConst()) {
3210 newNode
= new AstNode(AST_REALVALUE
);
3211 if (type
== AST_NEG
)
3212 newNode
->realvalue
= -children
[0]->asReal(sign_hint
);
3214 newNode
->realvalue
= +children
[0]->asReal(sign_hint
);
3218 if (children
[0]->isConst())
3220 bool found_sure_true
= false;
3221 bool found_maybe_true
= false;
3223 if (children
[0]->type
== AST_CONSTANT
)
3224 for (auto &bit
: children
[0]->bits
) {
3225 if (bit
== RTLIL::State::S1
)
3226 found_sure_true
= true;
3227 if (bit
> RTLIL::State::S1
)
3228 found_maybe_true
= true;
3231 found_sure_true
= children
[0]->asReal(sign_hint
) != 0;
3233 AstNode
*choice
= NULL
, *not_choice
= NULL
;
3234 if (found_sure_true
)
3235 choice
= children
[1], not_choice
= children
[2];
3236 else if (!found_maybe_true
)
3237 choice
= children
[2], not_choice
= children
[1];
3239 if (choice
!= NULL
) {
3240 if (choice
->type
== AST_CONSTANT
) {
3241 int other_width_hint
= width_hint
;
3242 bool other_sign_hint
= sign_hint
, other_real
= false;
3243 not_choice
->detectSignWidth(other_width_hint
, other_sign_hint
, &other_real
);
3245 newNode
= new AstNode(AST_REALVALUE
);
3246 choice
->detectSignWidth(width_hint
, sign_hint
);
3247 newNode
->realvalue
= choice
->asReal(sign_hint
);
3249 RTLIL::Const y
= choice
->bitsAsConst(width_hint
, sign_hint
);
3250 if (choice
->is_string
&& y
.bits
.size() % 8 == 0 && sign_hint
== false)
3251 newNode
= mkconst_str(y
.bits
);
3253 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3256 if (choice
->isConst()) {
3257 newNode
= choice
->clone();
3259 } else if (children
[1]->type
== AST_CONSTANT
&& children
[2]->type
== AST_CONSTANT
) {
3260 RTLIL::Const a
= children
[1]->bitsAsConst(width_hint
, sign_hint
);
3261 RTLIL::Const b
= children
[2]->bitsAsConst(width_hint
, sign_hint
);
3262 log_assert(a
.bits
.size() == b
.bits
.size());
3263 for (size_t i
= 0; i
< a
.bits
.size(); i
++)
3264 if (a
.bits
[i
] != b
.bits
[i
])
3265 a
.bits
[i
] = RTLIL::State::Sx
;
3266 newNode
= mkconst_bits(a
.bits
, sign_hint
);
3267 } else if (children
[1]->isConst() && children
[2]->isConst()) {
3268 newNode
= new AstNode(AST_REALVALUE
);
3269 if (children
[1]->asReal(sign_hint
) == children
[2]->asReal(sign_hint
))
3270 newNode
->realvalue
= children
[1]->asReal(sign_hint
);
3272 // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
3273 // the data type in question should be returned if the ?: is ambiguous. The
3274 // value in Table 7-1 for the 'real' type is 0.0.
3275 newNode
->realvalue
= 0.0;
3280 string_op
= !children
.empty();
3281 for (auto it
= children
.begin(); it
!= children
.end(); it
++) {
3282 if ((*it
)->type
!= AST_CONSTANT
)
3284 if (!(*it
)->is_string
)
3286 tmp_bits
.insert(tmp_bits
.end(), (*it
)->bits
.begin(), (*it
)->bits
.end());
3288 newNode
= string_op
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
3291 if (children
.at(0)->type
!= AST_CONSTANT
|| children
.at(1)->type
!= AST_CONSTANT
)
3293 for (int i
= 0; i
< children
[0]->bitsAsConst().as_int(); i
++)
3294 tmp_bits
.insert(tmp_bits
.end(), children
.at(1)->bits
.begin(), children
.at(1)->bits
.end());
3295 newNode
= children
.at(1)->is_string
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
3303 // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
3306 // fprintf(stderr, "----\n");
3307 // dumpAst(stderr, "- ");
3308 // newNode->dumpAst(stderr, "+ ");
3309 log_assert(newNode
!= NULL
);
3310 newNode
->filename
= filename
;
3311 newNode
->location
= location
;
3312 newNode
->cloneInto(this);
3314 did_something
= true;
3320 recursion_counter
--;
3321 return did_something
;
3324 static void replace_result_wire_name_in_function(AstNode
*node
, std::string
&from
, std::string
&to
)
3326 for (auto &it
: node
->children
)
3327 replace_result_wire_name_in_function(it
, from
, to
);
3328 if (node
->str
== from
)
3332 // replace a readmem[bh] TCALL ast node with a block of memory assignments
3333 AstNode
*AstNode::readmem(bool is_readmemh
, std::string mem_filename
, AstNode
*memory
, int start_addr
, int finish_addr
, bool unconditional_init
)
3335 int mem_width
, mem_size
, addr_bits
;
3336 memory
->meminfo(mem_width
, mem_size
, addr_bits
);
3338 AstNode
*block
= new AstNode(AST_BLOCK
);
3340 AstNode
*meminit
= nullptr;
3341 int next_meminit_cursor
=0;
3342 vector
<State
> meminit_bits
;
3346 f
.open(mem_filename
.c_str());
3353 std::string path
= filename
.substr(0, filename
.find_last_of(slash
)+1);
3354 f
.open(path
+ mem_filename
.c_str());
3355 yosys_input_files
.insert(path
+ mem_filename
);
3357 yosys_input_files
.insert(mem_filename
);
3359 if (f
.fail() || GetSize(mem_filename
) == 0)
3360 log_file_error(filename
, location
.first_line
, "Can not open file `%s` for %s.\n", mem_filename
.c_str(), str
.c_str());
3362 log_assert(GetSize(memory
->children
) == 2 && memory
->children
[1]->type
== AST_RANGE
&& memory
->children
[1]->range_valid
);
3363 int range_left
= memory
->children
[1]->range_left
, range_right
= memory
->children
[1]->range_right
;
3364 int range_min
= min(range_left
, range_right
), range_max
= max(range_left
, range_right
);
3367 start_addr
= range_min
;
3369 if (finish_addr
< 0)
3370 finish_addr
= range_max
+ 1;
3372 bool in_comment
= false;
3373 int increment
= start_addr
<= finish_addr
? +1 : -1;
3374 int cursor
= start_addr
;
3378 std::string line
, token
;
3379 std::getline(f
, line
);
3381 for (int i
= 0; i
< GetSize(line
); i
++) {
3382 if (in_comment
&& line
.compare(i
, 2, "*/") == 0) {
3388 if (!in_comment
&& line
.compare(i
, 2, "/*") == 0)
3396 token
= next_token(line
, " \t\r\n");
3397 if (token
.empty() || token
.compare(0, 2, "//") == 0)
3400 if (token
[0] == '@') {
3401 token
= token
.substr(1);
3402 const char *nptr
= token
.c_str();
3404 cursor
= strtol(nptr
, &endptr
, 16);
3405 if (!*nptr
|| *endptr
)
3406 log_file_error(filename
, location
.first_line
, "Can not parse address `%s` for %s.\n", nptr
, str
.c_str());
3410 AstNode
*value
= VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width
, is_readmemh
? 'h' : 'b') + token
);
3412 if (unconditional_init
)
3414 if (meminit
== nullptr || cursor
!= next_meminit_cursor
)
3416 if (meminit
!= nullptr) {
3417 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
3418 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
3421 meminit
= new AstNode(AST_MEMINIT
);
3422 meminit
->children
.push_back(AstNode::mkconst_int(cursor
, false));
3423 meminit
->children
.push_back(nullptr);
3424 meminit
->children
.push_back(nullptr);
3425 meminit
->str
= memory
->str
;
3426 meminit
->id2ast
= memory
;
3427 meminit_bits
.clear();
3430 current_ast_mod
->children
.push_back(meminit
);
3431 next_meminit_cursor
= cursor
;
3435 next_meminit_cursor
++;
3436 meminit_bits
.insert(meminit_bits
.end(), value
->bits
.begin(), value
->bits
.end());
3441 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
, false))), value
));
3442 block
->children
.back()->children
[0]->str
= memory
->str
;
3443 block
->children
.back()->children
[0]->id2ast
= memory
;
3444 block
->children
.back()->children
[0]->was_checked
= true;
3447 cursor
+= increment
;
3448 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
3452 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
3456 if (meminit
!= nullptr) {
3457 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
3458 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
3464 // annotate the names of all wires and other named objects in a generate block
3465 void AstNode::expand_genblock(std::string index_var
, std::string prefix
, std::map
<std::string
, std::string
> &name_map
)
3467 if (!index_var
.empty() && type
== AST_IDENTIFIER
&& str
== index_var
) {
3468 if (children
.empty()) {
3469 current_scope
[index_var
]->children
[0]->cloneInto(this);
3471 AstNode
*p
= new AstNode(AST_LOCALPARAM
, current_scope
[index_var
]->children
[0]->clone());
3472 p
->str
= stringf("$genval$%d", autoidx
++);
3473 current_ast_mod
->children
.push_back(p
);
3479 if ((type
== AST_IDENTIFIER
|| type
== AST_FCALL
|| type
== AST_TCALL
|| type
== AST_WIRETYPE
) && name_map
.count(str
) > 0)
3480 str
= name_map
[str
];
3482 std::map
<std::string
, std::string
> backup_name_map
;
3484 for (size_t i
= 0; i
< children
.size(); i
++) {
3485 AstNode
*child
= children
[i
];
3486 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
||
3487 child
->type
== AST_FUNCTION
|| child
->type
== AST_TASK
|| child
->type
== AST_CELL
|| child
->type
== AST_TYPEDEF
|| child
->type
== AST_ENUM_ITEM
) {
3488 if (backup_name_map
.size() == 0)
3489 backup_name_map
= name_map
;
3490 std::string new_name
= prefix
[0] == '\\' ? prefix
.substr(1) : prefix
;
3491 size_t pos
= child
->str
.rfind('.');
3492 if (pos
== std::string::npos
)
3493 pos
= child
->str
[0] == '\\' && prefix
[0] == '\\' ? 1 : 0;
3496 new_name
= child
->str
.substr(0, pos
) + new_name
+ child
->str
.substr(pos
);
3497 if (new_name
[0] != '$' && new_name
[0] != '\\')
3498 new_name
= prefix
[0] + new_name
;
3499 name_map
[child
->str
] = new_name
;
3500 if (child
->type
== AST_FUNCTION
)
3501 replace_result_wire_name_in_function(child
, child
->str
, new_name
);
3503 child
->str
= new_name
;
3504 current_scope
[new_name
] = child
;
3506 if (child
->type
== AST_ENUM
){
3507 current_scope
[child
->str
] = child
;
3508 for (auto enode
: child
->children
){
3509 log_assert(enode
->type
== AST_ENUM_ITEM
);
3510 if (backup_name_map
.size() == 0)
3511 backup_name_map
= name_map
;
3512 std::string new_name
= prefix
[0] == '\\' ? prefix
.substr(1) : prefix
;
3513 size_t pos
= enode
->str
.rfind('.');
3514 if (pos
== std::string::npos
)
3515 pos
= enode
->str
[0] == '\\' && prefix
[0] == '\\' ? 1 : 0;
3518 new_name
= enode
->str
.substr(0, pos
) + new_name
+ enode
->str
.substr(pos
);
3519 if (new_name
[0] != '$' && new_name
[0] != '\\')
3520 new_name
= prefix
[0] + new_name
;
3521 name_map
[enode
->str
] = new_name
;
3523 enode
->str
= new_name
;
3524 current_scope
[new_name
] = enode
;
3529 for (size_t i
= 0; i
< children
.size(); i
++) {
3530 AstNode
*child
= children
[i
];
3531 // AST_PREFIX member names should not be prefixed; a nested AST_PREFIX
3532 // still needs to recursed-into
3533 if (type
== AST_PREFIX
&& i
== 1 && child
->type
== AST_IDENTIFIER
)
3535 if (child
->type
!= AST_FUNCTION
&& child
->type
!= AST_TASK
)
3536 child
->expand_genblock(index_var
, prefix
, name_map
);
3540 if (backup_name_map
.size() > 0)
3541 name_map
.swap(backup_name_map
);
3544 // rename stuff (used when tasks of functions are instantiated)
3545 void AstNode::replace_ids(const std::string
&prefix
, const std::map
<std::string
, std::string
> &rules
)
3547 if (type
== AST_BLOCK
)
3549 std::map
<std::string
, std::string
> new_rules
= rules
;
3550 std::string new_prefix
= prefix
+ str
;
3552 for (auto child
: children
)
3553 if (child
->type
== AST_WIRE
) {
3554 new_rules
[child
->str
] = new_prefix
+ child
->str
;
3555 child
->str
= new_prefix
+ child
->str
;
3558 for (auto child
: children
)
3559 if (child
->type
!= AST_WIRE
)
3560 child
->replace_ids(new_prefix
, new_rules
);
3564 if (type
== AST_IDENTIFIER
&& rules
.count(str
) > 0)
3565 str
= rules
.at(str
);
3566 for (auto child
: children
)
3567 child
->replace_ids(prefix
, rules
);
3571 // helper function for mem2reg_as_needed_pass1
3572 static void mark_memories_assign_lhs_complex(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
3573 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, AstNode
*that
)
3575 for (auto &child
: that
->children
)
3576 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, child
);
3578 if (that
->type
== AST_IDENTIFIER
&& that
->id2ast
&& that
->id2ast
->type
== AST_MEMORY
) {
3579 AstNode
*mem
= that
->id2ast
;
3580 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_CMPLX_LHS
))
3581 mem2reg_places
[mem
].insert(stringf("%s:%d", that
->filename
.c_str(), that
->location
.first_line
));
3582 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CMPLX_LHS
;
3586 // find memories that should be replaced by registers
3587 void AstNode::mem2reg_as_needed_pass1(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
3588 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, dict
<AstNode
*, uint32_t> &proc_flags
, uint32_t &flags
)
3590 uint32_t children_flags
= 0;
3591 int lhs_children_counter
= 0;
3593 if (type
== AST_TYPEDEF
)
3594 return; // don't touch content of typedefs
3596 if (type
== AST_ASSIGN
|| type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
)
3598 // mark all memories that are used in a complex expression on the left side of an assignment
3599 for (auto &lhs_child
: children
[0]->children
)
3600 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, lhs_child
);
3602 if (children
[0]->type
== AST_IDENTIFIER
&& children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
)
3604 AstNode
*mem
= children
[0]->id2ast
;
3606 // activate mem2reg if this is assigned in an async proc
3607 if (flags
& AstNode::MEM2REG_FL_ASYNC
) {
3608 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ASYNC
))
3609 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3610 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ASYNC
;
3613 // remember if this is assigned blocking (=)
3614 if (type
== AST_ASSIGN_EQ
) {
3615 if (!(proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
))
3616 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3617 proc_flags
[mem
] |= AstNode::MEM2REG_FL_EQ1
;
3620 // for proper (non-init) writes: remember if this is a constant index or not
3621 if ((flags
& MEM2REG_FL_INIT
) == 0) {
3622 if (children
[0]->children
.size() && children
[0]->children
[0]->type
== AST_RANGE
&& children
[0]->children
[0]->children
.size()) {
3623 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
)
3624 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CONST_LHS
;
3626 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_VAR_LHS
;
3630 // remember where this is
3631 if (flags
& MEM2REG_FL_INIT
) {
3632 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_INIT
))
3633 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3634 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_INIT
;
3636 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ELSE
))
3637 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3638 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ELSE
;
3642 lhs_children_counter
= 1;
3645 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
)
3647 AstNode
*mem
= id2ast
;
3649 // flag if used after blocking assignment (in same proc)
3650 if ((proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
) && !(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_EQ2
)) {
3651 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3652 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_EQ2
;
3656 // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg'
3657 if (type
== AST_MEMORY
&& (get_bool_attribute(ID::mem2reg
) || (flags
& AstNode::MEM2REG_FL_ALL
) || !is_reg
))
3658 mem2reg_candidates
[this] |= AstNode::MEM2REG_FL_FORCED
;
3660 if (type
== AST_MODULE
&& get_bool_attribute(ID::mem2reg
))
3661 children_flags
|= AstNode::MEM2REG_FL_ALL
;
3663 dict
<AstNode
*, uint32_t> *proc_flags_p
= NULL
;
3665 if (type
== AST_ALWAYS
) {
3666 int count_edge_events
= 0;
3667 for (auto child
: children
)
3668 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
3669 count_edge_events
++;
3670 if (count_edge_events
!= 1)
3671 children_flags
|= AstNode::MEM2REG_FL_ASYNC
;
3672 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
3675 if (type
== AST_INITIAL
) {
3676 children_flags
|= AstNode::MEM2REG_FL_INIT
;
3677 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
3680 uint32_t backup_flags
= flags
;
3681 flags
|= children_flags
;
3682 log_assert((flags
& ~0x000000ff) == 0);
3684 for (auto child
: children
)
3686 if (lhs_children_counter
> 0) {
3687 lhs_children_counter
--;
3688 if (child
->children
.size() && child
->children
[0]->type
== AST_RANGE
&& child
->children
[0]->children
.size()) {
3689 for (auto c
: child
->children
[0]->children
) {
3691 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
3693 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
3698 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
3700 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
3703 flags
&= ~children_flags
| backup_flags
;
3707 for (auto it
: *proc_flags_p
)
3708 log_assert((it
.second
& ~0xff000000) == 0);
3710 delete proc_flags_p
;
3714 bool AstNode::mem2reg_check(pool
<AstNode
*> &mem2reg_set
)
3716 if (type
!= AST_IDENTIFIER
|| !id2ast
|| !mem2reg_set
.count(id2ast
))
3719 if (children
.empty() || children
[0]->type
!= AST_RANGE
|| GetSize(children
[0]->children
) != 1)
3720 log_file_error(filename
, location
.first_line
, "Invalid array access.\n");
3725 void AstNode::mem2reg_remove(pool
<AstNode
*> &mem2reg_set
, vector
<AstNode
*> &delnodes
)
3727 log_assert(mem2reg_set
.count(this) == 0);
3729 if (mem2reg_set
.count(id2ast
))
3732 for (size_t i
= 0; i
< children
.size(); i
++) {
3733 if (mem2reg_set
.count(children
[i
]) > 0) {
3734 delnodes
.push_back(children
[i
]);
3735 children
.erase(children
.begin() + (i
--));
3737 children
[i
]->mem2reg_remove(mem2reg_set
, delnodes
);
3742 // actually replace memories with registers
3743 bool AstNode::mem2reg_as_needed_pass2(pool
<AstNode
*> &mem2reg_set
, AstNode
*mod
, AstNode
*block
, AstNode
*&async_block
)
3745 bool did_something
= false;
3747 if (type
== AST_BLOCK
)
3750 if (type
== AST_FUNCTION
|| type
== AST_TASK
)
3753 if (type
== AST_TYPEDEF
)
3756 if (type
== AST_MEMINIT
&& id2ast
&& mem2reg_set
.count(id2ast
))
3758 log_assert(children
[0]->type
== AST_CONSTANT
);
3759 log_assert(children
[1]->type
== AST_CONSTANT
);
3760 log_assert(children
[2]->type
== AST_CONSTANT
);
3762 int cursor
= children
[0]->asInt(false);
3763 Const data
= children
[1]->bitsAsConst();
3764 int length
= children
[2]->asInt(false);
3768 AstNode
*block
= new AstNode(AST_INITIAL
, new AstNode(AST_BLOCK
));
3769 mod
->children
.push_back(block
);
3770 block
= block
->children
[0];
3772 int wordsz
= GetSize(data
) / length
;
3774 for (int i
= 0; i
< length
; i
++) {
3775 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+i
, false))), mkconst_bits(data
.extract(i
*wordsz
, wordsz
).bits
, false)));
3776 block
->children
.back()->children
[0]->str
= str
;
3777 block
->children
.back()->children
[0]->id2ast
= id2ast
;
3778 block
->children
.back()->children
[0]->was_checked
= true;
3782 AstNode
*newNode
= new AstNode(AST_NONE
);
3783 newNode
->cloneInto(this);
3786 did_something
= true;
3789 if (type
== AST_ASSIGN
&& block
== NULL
&& children
[0]->mem2reg_check(mem2reg_set
))
3791 if (async_block
== NULL
) {
3792 async_block
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
3793 mod
->children
.push_back(async_block
);
3796 AstNode
*newNode
= clone();
3797 newNode
->type
= AST_ASSIGN_EQ
;
3798 newNode
->children
[0]->was_checked
= true;
3799 async_block
->children
[0]->children
.push_back(newNode
);
3801 newNode
= new AstNode(AST_NONE
);
3802 newNode
->cloneInto(this);
3805 did_something
= true;
3808 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->mem2reg_check(mem2reg_set
) &&
3809 children
[0]->children
[0]->children
[0]->type
!= AST_CONSTANT
)
3811 std::stringstream sstr
;
3812 sstr
<< "$mem2reg_wr$" << children
[0]->str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
3813 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
3815 int mem_width
, mem_size
, addr_bits
;
3816 bool mem_signed
= children
[0]->id2ast
->is_signed
;
3817 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
3819 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
3820 wire_addr
->str
= id_addr
;
3821 wire_addr
->is_reg
= true;
3822 wire_addr
->was_checked
= true;
3823 wire_addr
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
3824 mod
->children
.push_back(wire_addr
);
3825 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
3827 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
3828 wire_data
->str
= id_data
;
3829 wire_data
->is_reg
= true;
3830 wire_data
->was_checked
= true;
3831 wire_data
->is_signed
= mem_signed
;
3832 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
3833 mod
->children
.push_back(wire_data
);
3834 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
3836 log_assert(block
!= NULL
);
3837 size_t assign_idx
= 0;
3838 while (assign_idx
< block
->children
.size() && block
->children
[assign_idx
] != this)
3840 log_assert(assign_idx
< block
->children
.size());
3842 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
3843 assign_addr
->children
[0]->str
= id_addr
;
3844 assign_addr
->children
[0]->was_checked
= true;
3845 block
->children
.insert(block
->children
.begin()+assign_idx
+1, assign_addr
);
3847 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
3848 case_node
->children
[0]->str
= id_addr
;
3849 for (int i
= 0; i
< mem_size
; i
++) {
3850 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->children
[0]->integer
) != i
)
3852 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
3853 AstNode
*assign_reg
= new AstNode(type
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
3854 if (children
[0]->children
.size() == 2)
3855 assign_reg
->children
[0]->children
.push_back(children
[0]->children
[1]->clone());
3856 assign_reg
->children
[0]->str
= stringf("%s[%d]", children
[0]->str
.c_str(), i
);
3857 assign_reg
->children
[1]->str
= id_data
;
3858 cond_node
->children
[1]->children
.push_back(assign_reg
);
3859 case_node
->children
.push_back(cond_node
);
3861 block
->children
.insert(block
->children
.begin()+assign_idx
+2, case_node
);
3863 children
[0]->delete_children();
3864 children
[0]->range_valid
= false;
3865 children
[0]->id2ast
= NULL
;
3866 children
[0]->str
= id_data
;
3867 type
= AST_ASSIGN_EQ
;
3868 children
[0]->was_checked
= true;
3870 did_something
= true;
3873 if (mem2reg_check(mem2reg_set
))
3875 AstNode
*bit_part_sel
= NULL
;
3876 if (children
.size() == 2)
3877 bit_part_sel
= children
[1]->clone();
3879 if (children
[0]->children
[0]->type
== AST_CONSTANT
)
3881 int id
= children
[0]->children
[0]->integer
;
3882 str
= stringf("%s[%d]", str
.c_str(), id
);
3885 range_valid
= false;
3890 std::stringstream sstr
;
3891 sstr
<< "$mem2reg_rd$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
3892 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
3894 int mem_width
, mem_size
, addr_bits
;
3895 bool mem_signed
= id2ast
->is_signed
;
3896 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
3898 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
3899 wire_addr
->str
= id_addr
;
3900 wire_addr
->is_reg
= true;
3901 wire_addr
->was_checked
= true;
3903 wire_addr
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
3904 mod
->children
.push_back(wire_addr
);
3905 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
3907 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
3908 wire_data
->str
= id_data
;
3909 wire_data
->is_reg
= true;
3910 wire_data
->was_checked
= true;
3911 wire_data
->is_signed
= mem_signed
;
3913 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
3914 mod
->children
.push_back(wire_data
);
3915 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
3917 AstNode
*assign_addr
= new AstNode(block
? AST_ASSIGN_EQ
: AST_ASSIGN
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->clone());
3918 assign_addr
->children
[0]->str
= id_addr
;
3919 assign_addr
->children
[0]->was_checked
= true;
3921 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
3922 case_node
->children
[0]->str
= id_addr
;
3924 for (int i
= 0; i
< mem_size
; i
++) {
3925 if (children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->integer
) != i
)
3927 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
3928 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
3929 assign_reg
->children
[0]->str
= id_data
;
3930 assign_reg
->children
[0]->was_checked
= true;
3931 assign_reg
->children
[1]->str
= stringf("%s[%d]", str
.c_str(), i
);
3932 cond_node
->children
[1]->children
.push_back(assign_reg
);
3933 case_node
->children
.push_back(cond_node
);
3936 std::vector
<RTLIL::State
> x_bits
;
3937 for (int i
= 0; i
< mem_width
; i
++)
3938 x_bits
.push_back(RTLIL::State::Sx
);
3940 AstNode
*cond_node
= new AstNode(AST_COND
, new AstNode(AST_DEFAULT
), new AstNode(AST_BLOCK
));
3941 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), AstNode::mkconst_bits(x_bits
, false));
3942 assign_reg
->children
[0]->str
= id_data
;
3943 assign_reg
->children
[0]->was_checked
= true;
3944 cond_node
->children
[1]->children
.push_back(assign_reg
);
3945 case_node
->children
.push_back(cond_node
);
3949 size_t assign_idx
= 0;
3950 while (assign_idx
< block
->children
.size() && !block
->children
[assign_idx
]->contains(this))
3952 log_assert(assign_idx
< block
->children
.size());
3953 block
->children
.insert(block
->children
.begin()+assign_idx
, case_node
);
3954 block
->children
.insert(block
->children
.begin()+assign_idx
, assign_addr
);
3958 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
3959 proc
->children
[0]->children
.push_back(case_node
);
3960 mod
->children
.push_back(proc
);
3961 mod
->children
.push_back(assign_addr
);
3965 range_valid
= false;
3971 children
.push_back(bit_part_sel
);
3973 did_something
= true;
3976 log_assert(id2ast
== NULL
|| mem2reg_set
.count(id2ast
) == 0);
3978 auto children_list
= children
;
3979 for (size_t i
= 0; i
< children_list
.size(); i
++)
3980 if (children_list
[i
]->mem2reg_as_needed_pass2(mem2reg_set
, mod
, block
, async_block
))
3981 did_something
= true;
3983 return did_something
;
3986 // calculate memory dimensions
3987 void AstNode::meminfo(int &mem_width
, int &mem_size
, int &addr_bits
)
3989 log_assert(type
== AST_MEMORY
);
3991 mem_width
= children
[0]->range_left
- children
[0]->range_right
+ 1;
3992 mem_size
= children
[1]->range_left
- children
[1]->range_right
;
3996 mem_size
+= min(children
[1]->range_left
, children
[1]->range_right
) + 1;
3999 while ((1 << addr_bits
) < mem_size
)
4003 bool AstNode::has_const_only_constructs(bool &recommend_const_eval
)
4005 if (type
== AST_FOR
)
4006 recommend_const_eval
= true;
4007 if (type
== AST_WHILE
|| type
== AST_REPEAT
)
4009 if (type
== AST_FCALL
&& current_scope
.count(str
))
4010 if (current_scope
[str
]->has_const_only_constructs(recommend_const_eval
))
4012 for (auto child
: children
)
4013 if (child
->AstNode::has_const_only_constructs(recommend_const_eval
))
4018 bool AstNode::is_simple_const_expr()
4020 if (type
== AST_IDENTIFIER
)
4022 for (auto child
: children
)
4023 if (!child
->is_simple_const_expr())
4028 // helper function for AstNode::eval_const_function()
4029 void AstNode::replace_variables(std::map
<std::string
, AstNode::varinfo_t
> &variables
, AstNode
*fcall
)
4031 if (type
== AST_IDENTIFIER
&& variables
.count(str
)) {
4032 int offset
= variables
.at(str
).offset
, width
= variables
.at(str
).val
.bits
.size();
4033 if (!children
.empty()) {
4034 if (children
.size() != 1 || children
.at(0)->type
!= AST_RANGE
)
4035 log_file_error(filename
, location
.first_line
, "Memory access in constant function is not supported\n%s:%d.%d-%d.%d: ...called from here.\n",
4036 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4037 children
.at(0)->replace_variables(variables
, fcall
);
4038 while (simplify(true, false, false, 1, -1, false, true)) { }
4039 if (!children
.at(0)->range_valid
)
4040 log_file_error(filename
, location
.first_line
, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
4041 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4042 offset
= min(children
.at(0)->range_left
, children
.at(0)->range_right
);
4043 width
= min(std::abs(children
.at(0)->range_left
- children
.at(0)->range_right
) + 1, width
);
4045 offset
-= variables
.at(str
).offset
;
4046 std::vector
<RTLIL::State
> &var_bits
= variables
.at(str
).val
.bits
;
4047 std::vector
<RTLIL::State
> new_bits(var_bits
.begin() + offset
, var_bits
.begin() + offset
+ width
);
4048 AstNode
*newNode
= mkconst_bits(new_bits
, variables
.at(str
).is_signed
);
4049 newNode
->cloneInto(this);
4054 for (auto &child
: children
)
4055 child
->replace_variables(variables
, fcall
);
4058 // evaluate functions with all-const arguments
4059 AstNode
*AstNode::eval_const_function(AstNode
*fcall
)
4061 std::map
<std::string
, AstNode
*> backup_scope
;
4062 std::map
<std::string
, AstNode::varinfo_t
> variables
;
4063 AstNode
*block
= new AstNode(AST_BLOCK
);
4066 for (auto child
: children
)
4068 if (child
->type
== AST_WIRE
)
4070 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
4071 if (!child
->range_valid
)
4072 log_file_error(child
->filename
, child
->location
.first_line
, "Can't determine size of variable %s\n%s:%d.%d-%d.%d: ... called from here.\n",
4073 child
->str
.c_str(), fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4074 variables
[child
->str
].val
= RTLIL::Const(RTLIL::State::Sx
, abs(child
->range_left
- child
->range_right
)+1);
4075 variables
[child
->str
].offset
= min(child
->range_left
, child
->range_right
);
4076 variables
[child
->str
].is_signed
= child
->is_signed
;
4077 if (child
->is_input
&& argidx
< fcall
->children
.size())
4078 variables
[child
->str
].val
= fcall
->children
.at(argidx
++)->bitsAsConst(variables
[child
->str
].val
.bits
.size());
4079 backup_scope
[child
->str
] = current_scope
[child
->str
];
4080 current_scope
[child
->str
] = child
;
4084 block
->children
.push_back(child
->clone());
4087 log_assert(variables
.count(str
) != 0);
4089 while (!block
->children
.empty())
4091 AstNode
*stmt
= block
->children
.front();
4094 log("-----------------------------------\n");
4095 for (auto &it
: variables
)
4096 log("%20s %40s\n", it
.first
.c_str(), log_signal(it
.second
.val
));
4097 stmt
->dumpAst(NULL
, "stmt> ");
4100 if (stmt
->type
== AST_ASSIGN_EQ
)
4102 if (stmt
->children
.at(0)->type
== AST_IDENTIFIER
&& stmt
->children
.at(0)->children
.size() != 0 &&
4103 stmt
->children
.at(0)->children
.at(0)->type
== AST_RANGE
)
4104 stmt
->children
.at(0)->children
.at(0)->replace_variables(variables
, fcall
);
4105 stmt
->children
.at(1)->replace_variables(variables
, fcall
);
4106 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
4108 if (stmt
->type
!= AST_ASSIGN_EQ
)
4111 if (stmt
->children
.at(1)->type
!= AST_CONSTANT
)
4112 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here. X\n",
4113 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4115 if (stmt
->children
.at(0)->type
!= AST_IDENTIFIER
)
4116 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Unsupported composite left hand side in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4117 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4119 if (!variables
.count(stmt
->children
.at(0)->str
))
4120 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Assignment to non-local variable in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4121 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4123 if (stmt
->children
.at(0)->children
.empty()) {
4124 variables
[stmt
->children
.at(0)->str
].val
= stmt
->children
.at(1)->bitsAsConst(variables
[stmt
->children
.at(0)->str
].val
.bits
.size());
4126 AstNode
*range
= stmt
->children
.at(0)->children
.at(0);
4127 if (!range
->range_valid
)
4128 log_file_error(range
->filename
, range
->location
.first_line
, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
4129 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4130 int offset
= min(range
->range_left
, range
->range_right
);
4131 int width
= std::abs(range
->range_left
- range
->range_right
) + 1;
4132 varinfo_t
&v
= variables
[stmt
->children
.at(0)->str
];
4133 RTLIL::Const r
= stmt
->children
.at(1)->bitsAsConst(v
.val
.bits
.size());
4134 for (int i
= 0; i
< width
; i
++)
4135 v
.val
.bits
.at(i
+offset
-v
.offset
) = r
.bits
.at(i
);
4138 delete block
->children
.front();
4139 block
->children
.erase(block
->children
.begin());
4143 if (stmt
->type
== AST_FOR
)
4145 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(0));
4146 stmt
->children
.at(3)->children
.push_back(stmt
->children
.at(2));
4147 stmt
->children
.erase(stmt
->children
.begin() + 2);
4148 stmt
->children
.erase(stmt
->children
.begin());
4149 stmt
->type
= AST_WHILE
;
4153 if (stmt
->type
== AST_WHILE
)
4155 AstNode
*cond
= stmt
->children
.at(0)->clone();
4156 cond
->replace_variables(variables
, fcall
);
4157 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
4159 if (cond
->type
!= AST_CONSTANT
)
4160 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4161 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4163 if (cond
->asBool()) {
4164 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
4166 delete block
->children
.front();
4167 block
->children
.erase(block
->children
.begin());
4174 if (stmt
->type
== AST_REPEAT
)
4176 AstNode
*num
= stmt
->children
.at(0)->clone();
4177 num
->replace_variables(variables
, fcall
);
4178 while (num
->simplify(true, false, false, 1, -1, false, true)) { }
4180 if (num
->type
!= AST_CONSTANT
)
4181 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4182 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4184 block
->children
.erase(block
->children
.begin());
4185 for (int i
= 0; i
< num
->bitsAsConst().as_int(); i
++)
4186 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
4193 if (stmt
->type
== AST_CASE
)
4195 AstNode
*expr
= stmt
->children
.at(0)->clone();
4196 expr
->replace_variables(variables
, fcall
);
4197 while (expr
->simplify(true, false, false, 1, -1, false, true)) { }
4199 AstNode
*sel_case
= NULL
;
4200 for (size_t i
= 1; i
< stmt
->children
.size(); i
++)
4202 bool found_match
= false;
4203 log_assert(stmt
->children
.at(i
)->type
== AST_COND
|| stmt
->children
.at(i
)->type
== AST_CONDX
|| stmt
->children
.at(i
)->type
== AST_CONDZ
);
4205 if (stmt
->children
.at(i
)->children
.front()->type
== AST_DEFAULT
) {
4206 sel_case
= stmt
->children
.at(i
)->children
.back();
4210 for (size_t j
= 0; j
+1 < stmt
->children
.at(i
)->children
.size() && !found_match
; j
++)
4212 AstNode
*cond
= stmt
->children
.at(i
)->children
.at(j
)->clone();
4213 cond
->replace_variables(variables
, fcall
);
4215 cond
= new AstNode(AST_EQ
, expr
->clone(), cond
);
4216 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
4218 if (cond
->type
!= AST_CONSTANT
)
4219 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4220 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4222 found_match
= cond
->asBool();
4227 sel_case
= stmt
->children
.at(i
)->children
.back();
4232 block
->children
.erase(block
->children
.begin());
4234 block
->children
.insert(block
->children
.begin(), sel_case
->clone());
4240 if (stmt
->type
== AST_BLOCK
)
4242 block
->children
.erase(block
->children
.begin());
4243 block
->children
.insert(block
->children
.begin(), stmt
->children
.begin(), stmt
->children
.end());
4244 stmt
->children
.clear();
4249 log_file_error(stmt
->filename
, stmt
->location
.first_line
, "Unsupported language construct in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
4250 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4256 for (auto &it
: backup_scope
)
4257 if (it
.second
== NULL
)
4258 current_scope
.erase(it
.first
);
4260 current_scope
[it
.first
] = it
.second
;
4262 return AstNode::mkconst_bits(variables
.at(str
).val
.bits
, variables
.at(str
).is_signed
);
4265 void AstNode::allocateDefaultEnumValues()
4267 log_assert(type
==AST_ENUM
);
4268 int last_enum_int
= -1;
4269 for (auto node
: children
) {
4270 log_assert(node
->type
==AST_ENUM_ITEM
);
4271 node
->attributes
[ID::enum_base_type
] = mkconst_str(str
);
4272 for (size_t i
= 0; i
< node
->children
.size(); i
++) {
4273 switch (node
->children
[i
]->type
) {
4275 // replace with auto-incremented constant
4276 delete node
->children
[i
];
4277 node
->children
[i
] = AstNode::mkconst_int(++last_enum_int
, true);
4280 // explicit constant (or folded expression)
4281 // TODO: can't extend 'x or 'z item
4282 last_enum_int
= node
->children
[i
]->integer
;
4288 // TODO: range check