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 // convert the AST into a simpler AST that has all parameters substituted by their
172 // values, unrolled for-loops, expanded generate blocks, etc. when this function
173 // is done with an AST it can be converted into RTLIL using genRTLIL().
175 // this function also does all name resolving and sets the id2ast member of all
176 // nodes that link to a different node using names and lexical scoping.
177 bool AstNode::simplify(bool const_fold
, bool at_zero
, bool in_lvalue
, int stage
, int width_hint
, bool sign_hint
, bool in_param
)
179 static int recursion_counter
= 0;
180 static bool deep_recursion_warning
= false;
182 if (recursion_counter
++ == 1000 && deep_recursion_warning
) {
183 log_warning("Deep recursion in AST simplifier.\nDoes this design contain insanely long expressions?\n");
184 deep_recursion_warning
= false;
187 AstNode
*newNode
= NULL
;
188 bool did_something
= false;
191 log("-------------\n");
192 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);
193 log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
194 int(const_fold
), int(at_zero
), int(in_lvalue
), int(stage
), int(width_hint
), int(sign_hint
), int(in_param
));
195 // dumpAst(NULL, "> ");
200 log_assert(type
== AST_MODULE
|| type
== AST_INTERFACE
);
202 deep_recursion_warning
= true;
203 while (simplify(const_fold
, at_zero
, in_lvalue
, 1, width_hint
, sign_hint
, in_param
)) { }
205 if (!flag_nomem2reg
&& !get_bool_attribute(ID::nomem2reg
))
207 dict
<AstNode
*, pool
<std::string
>> mem2reg_places
;
208 dict
<AstNode
*, uint32_t> mem2reg_candidates
, dummy_proc_flags
;
209 uint32_t flags
= flag_mem2reg
? AstNode::MEM2REG_FL_ALL
: 0;
210 mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, dummy_proc_flags
, flags
);
212 pool
<AstNode
*> mem2reg_set
;
213 for (auto &it
: mem2reg_candidates
)
215 AstNode
*mem
= it
.first
;
216 uint32_t memflags
= it
.second
;
217 bool this_nomeminit
= flag_nomeminit
;
218 log_assert((memflags
& ~0x00ffff00) == 0);
220 if (mem
->get_bool_attribute(ID::nomem2reg
))
223 if (mem
->get_bool_attribute(ID::nomeminit
) || get_bool_attribute(ID::nomeminit
))
224 this_nomeminit
= true;
226 if (memflags
& AstNode::MEM2REG_FL_FORCED
)
227 goto silent_activate
;
229 if (memflags
& AstNode::MEM2REG_FL_EQ2
)
230 goto verbose_activate
;
232 if (memflags
& AstNode::MEM2REG_FL_SET_ASYNC
)
233 goto verbose_activate
;
235 if ((memflags
& AstNode::MEM2REG_FL_SET_INIT
) && (memflags
& AstNode::MEM2REG_FL_SET_ELSE
) && this_nomeminit
)
236 goto verbose_activate
;
238 if (memflags
& AstNode::MEM2REG_FL_CMPLX_LHS
)
239 goto verbose_activate
;
241 if ((memflags
& AstNode::MEM2REG_FL_CONST_LHS
) && !(memflags
& AstNode::MEM2REG_FL_VAR_LHS
))
242 goto verbose_activate
;
244 // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
248 if (mem2reg_set
.count(mem
) == 0) {
249 std::string message
= stringf("Replacing memory %s with list of registers.", mem
->str
.c_str());
250 bool first_element
= true;
251 for (auto &place
: mem2reg_places
[it
.first
]) {
252 message
+= stringf("%s%s", first_element
? " See " : ", ", place
.c_str());
253 first_element
= false;
255 log_warning("%s\n", message
.c_str());
259 // log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
260 mem2reg_set
.insert(mem
);
263 for (auto node
: mem2reg_set
)
265 int mem_width
, mem_size
, addr_bits
;
266 node
->meminfo(mem_width
, mem_size
, addr_bits
);
268 int data_range_left
= node
->children
[0]->range_left
;
269 int data_range_right
= node
->children
[0]->range_right
;
271 if (node
->children
[0]->range_swapped
)
272 std::swap(data_range_left
, data_range_right
);
274 for (int i
= 0; i
< mem_size
; i
++) {
275 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
276 mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
277 reg
->str
= stringf("%s[%d]", node
->str
.c_str(), i
);
279 reg
->is_signed
= node
->is_signed
;
280 for (auto &it
: node
->attributes
)
281 if (it
.first
!= ID::mem2reg
)
282 reg
->attributes
.emplace(it
.first
, it
.second
->clone());
283 reg
->filename
= node
->filename
;
284 reg
->location
= node
->location
;
285 children
.push_back(reg
);
286 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
290 AstNode
*async_block
= NULL
;
291 while (mem2reg_as_needed_pass2(mem2reg_set
, this, NULL
, async_block
)) { }
293 vector
<AstNode
*> delnodes
;
294 mem2reg_remove(mem2reg_set
, delnodes
);
296 for (auto node
: delnodes
)
300 while (simplify(const_fold
, at_zero
, in_lvalue
, 2, width_hint
, sign_hint
, in_param
)) { }
305 current_filename
= filename
;
307 // we do not look inside a task or function
308 // (but as soon as a task or function is instantiated we process the generated AST as usual)
309 if (type
== AST_FUNCTION
|| type
== AST_TASK
) {
314 // deactivate all calls to non-synthesis system tasks
315 // note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
316 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && (str
== "$strobe" || str
== "$monitor" || str
== "$time" ||
317 str
== "$dumpfile" || str
== "$dumpvars" || str
== "$dumpon" || str
== "$dumpoff" || str
== "$dumpall")) {
318 log_file_warning(filename
, location
.first_line
, "Ignoring call to system %s %s.\n", type
== AST_FCALL
? "function" : "task", str
.c_str());
323 if ((type
== AST_TCALL
) && (str
== "$display" || str
== "$write") && (!current_always
|| current_always
->type
!= AST_INITIAL
)) {
324 log_file_warning(filename
, location
.first_line
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
329 // print messages if this a call to $display() or $write()
330 // This code implements only a small subset of Verilog-2005 $display() format specifiers,
331 // but should be good enough for most uses
332 if ((type
== AST_TCALL
) && ((str
== "$display") || (str
== "$write")))
334 int nargs
= GetSize(children
);
336 log_file_error(filename
, location
.first_line
, "System task `%s' got %d arguments, expected >= 1.\n",
337 str
.c_str(), int(children
.size()));
339 // First argument is the format string
340 AstNode
*node_string
= children
[0];
341 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
342 if (node_string
->type
!= AST_CONSTANT
)
343 log_file_error(filename
, location
.first_line
, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str
.c_str());
344 std::string sformat
= node_string
->bitsAsConst().decode_string();
345 std::string sout
= process_format_str(sformat
, 1, stage
, width_hint
, sign_hint
);
346 // Finally, print the message (only include a \n for $display, not for $write)
347 log("%s", sout
.c_str());
348 if (str
== "$display")
354 // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
355 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
)
357 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
))
360 // in certain cases a function must be evaluated constant. this is what in_param controls.
361 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_PREFIX
)
364 std::map
<std::string
, AstNode
*> backup_scope
;
366 // create name resolution entries for all objects with names
367 // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
368 if (type
== AST_MODULE
) {
369 current_scope
.clear();
370 std::map
<std::string
, AstNode
*> this_wire_scope
;
371 for (size_t i
= 0; i
< children
.size(); i
++) {
372 AstNode
*node
= children
[i
];
374 if (node
->type
== AST_WIRE
) {
375 if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
376 for (auto c
: node
->children
[0]->children
) {
377 if (!c
->is_simple_const_expr()) {
378 if (attributes
.count(ID::dynports
))
379 delete attributes
.at(ID::dynports
);
380 attributes
[ID::dynports
] = AstNode::mkconst_int(1, true);
384 if (this_wire_scope
.count(node
->str
) > 0) {
385 AstNode
*first_node
= this_wire_scope
[node
->str
];
386 if (first_node
->is_input
&& node
->is_reg
)
387 goto wires_are_incompatible
;
388 if (!node
->is_input
&& !node
->is_output
&& node
->is_reg
&& node
->children
.size() == 0)
389 goto wires_are_compatible
;
390 if (first_node
->children
.size() == 0 && node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
391 AstNode
*r
= node
->children
[0];
392 if (r
->range_valid
&& r
->range_left
== 0 && r
->range_right
== 0) {
394 node
->children
.pop_back();
397 if (first_node
->children
.size() != node
->children
.size())
398 goto wires_are_incompatible
;
399 for (size_t j
= 0; j
< node
->children
.size(); j
++) {
400 AstNode
*n1
= first_node
->children
[j
], *n2
= node
->children
[j
];
401 if (n1
->type
== AST_RANGE
&& n2
->type
== AST_RANGE
&& n1
->range_valid
&& n2
->range_valid
) {
402 if (n1
->range_left
!= n2
->range_left
)
403 goto wires_are_incompatible
;
404 if (n1
->range_right
!= n2
->range_right
)
405 goto wires_are_incompatible
;
406 } else if (*n1
!= *n2
)
407 goto wires_are_incompatible
;
409 if (first_node
->range_left
!= node
->range_left
)
410 goto wires_are_incompatible
;
411 if (first_node
->range_right
!= node
->range_right
)
412 goto wires_are_incompatible
;
413 if (first_node
->port_id
== 0 && (node
->is_input
|| node
->is_output
))
414 goto wires_are_incompatible
;
415 wires_are_compatible
:
417 first_node
->is_input
= true;
419 first_node
->is_output
= true;
421 first_node
->is_reg
= true;
423 first_node
->is_logic
= true;
425 first_node
->is_signed
= true;
426 for (auto &it
: node
->attributes
) {
427 if (first_node
->attributes
.count(it
.first
) > 0)
428 delete first_node
->attributes
[it
.first
];
429 first_node
->attributes
[it
.first
] = it
.second
->clone();
431 children
.erase(children
.begin()+(i
--));
432 did_something
= true;
435 wires_are_incompatible
:
437 log_file_error(filename
, location
.first_line
, "Incompatible re-declaration of wire %s.\n", node
->str
.c_str());
440 this_wire_scope
[node
->str
] = node
;
442 // these nodes appear at the top level in a module and can define names
443 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
444 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
|| node
->type
== AST_CELL
||
445 node
->type
== AST_TYPEDEF
) {
446 backup_scope
[node
->str
] = current_scope
[node
->str
];
447 current_scope
[node
->str
] = node
;
449 if (node
->type
== AST_ENUM
) {
450 current_scope
[node
->str
] = node
;
451 for (auto enode
: node
->children
) {
452 log_assert(enode
->type
==AST_ENUM_ITEM
);
453 if (current_scope
.count(enode
->str
) == 0)
454 current_scope
[enode
->str
] = enode
;
456 log_file_error(filename
, location
.first_line
, "enum item %s already exists\n", enode
->str
.c_str());
460 for (size_t i
= 0; i
< children
.size(); i
++) {
461 AstNode
*node
= children
[i
];
462 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
)
463 while (node
->simplify(true, false, false, 1, -1, false, node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
))
464 did_something
= true;
465 if (node
->type
== AST_ENUM
) {
466 for (auto enode
YS_ATTRIBUTE(unused
) : node
->children
){
467 log_assert(enode
->type
==AST_ENUM_ITEM
);
468 while (node
->simplify(true, false, false, 1, -1, false, in_param
))
469 did_something
= true;
475 // create name resolution entries for all objects with names
476 if (type
== AST_PACKAGE
) {
477 //add names to package scope
478 for (size_t i
= 0; i
< children
.size(); i
++) {
479 AstNode
*node
= children
[i
];
480 // these nodes appear at the top level in a package and can define names
481 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_TYPEDEF
) {
482 current_scope
[node
->str
] = node
;
484 if (node
->type
== AST_ENUM
) {
485 current_scope
[node
->str
] = node
;
486 for (auto enode
: node
->children
) {
487 log_assert(enode
->type
==AST_ENUM_ITEM
);
488 if (current_scope
.count(enode
->str
) == 0)
489 current_scope
[enode
->str
] = enode
;
491 log_file_error(filename
, location
.first_line
, "enum item %s already exists in package\n", enode
->str
.c_str());
498 auto backup_current_block
= current_block
;
499 auto backup_current_block_child
= current_block_child
;
500 auto backup_current_top_block
= current_top_block
;
501 auto backup_current_always
= current_always
;
502 auto backup_current_always_clocked
= current_always_clocked
;
504 if (type
== AST_ALWAYS
|| type
== AST_INITIAL
)
506 if (current_always
!= nullptr)
507 log_file_error(filename
, location
.first_line
, "Invalid nesting of always blocks and/or initializations.\n");
509 current_always
= this;
510 current_always_clocked
= false;
512 if (type
== AST_ALWAYS
)
513 for (auto child
: children
) {
514 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
515 current_always_clocked
= true;
516 if (child
->type
== AST_EDGE
&& GetSize(child
->children
) == 1 &&
517 child
->children
[0]->type
== AST_IDENTIFIER
&& child
->children
[0]->str
== "\\$global_clock")
518 current_always_clocked
= true;
522 int backup_width_hint
= width_hint
;
523 bool backup_sign_hint
= sign_hint
;
525 bool detect_width_simple
= false;
526 bool child_0_is_self_determined
= false;
527 bool child_1_is_self_determined
= false;
528 bool child_2_is_self_determined
= false;
529 bool children_are_self_determined
= false;
530 bool reset_width_after_children
= false;
537 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, true, stage
, -1, false, in_param
) == true)
538 did_something
= true;
539 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
) == true)
540 did_something
= true;
541 children
[0]->detectSignWidth(backup_width_hint
, backup_sign_hint
);
542 children
[1]->detectSignWidth(width_hint
, sign_hint
);
543 width_hint
= max(width_hint
, backup_width_hint
);
544 child_0_is_self_determined
= true;
545 // test only once, before optimizations and memory mappings but after assignment LHS was mapped to an identifier
546 if (children
[0]->id2ast
&& !children
[0]->was_checked
) {
547 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->id2ast
->is_logic
)
548 children
[0]->id2ast
->is_reg
= true; // if logic type is used in a block asignment
549 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && !children
[0]->id2ast
->is_reg
)
550 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
);
551 if (type
== AST_ASSIGN
&& children
[0]->id2ast
->is_reg
) {
552 bool is_rand_reg
= false;
553 if (children
[1]->type
== AST_FCALL
) {
554 if (children
[1]->str
== "\\$anyconst")
556 if (children
[1]->str
== "\\$anyseq")
558 if (children
[1]->str
== "\\$allconst")
560 if (children
[1]->str
== "\\$allseq")
564 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
);
566 children
[0]->was_checked
= true;
571 //log("\nENUM %s: %d child %d\n", str.c_str(), basic_prep, children[0]->basic_prep);
573 for (auto item_node
: children
) {
574 while (!item_node
->basic_prep
&& item_node
->simplify(false, false, false, stage
, -1, false, in_param
))
575 did_something
= true;
577 // allocate values (called more than once)
578 allocateDefaultEnumValues();
584 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, true) == true)
585 did_something
= true;
586 children
[0]->detectSignWidth(width_hint
, sign_hint
);
587 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
588 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, true) == true)
589 did_something
= true;
590 if (!children
[1]->range_valid
)
591 log_file_error(filename
, location
.first_line
, "Non-constant width range on parameter decl.\n");
592 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
596 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, in_param
))
597 did_something
= true;
598 children
[0]->detectSignWidth(width_hint
, sign_hint
);
599 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
600 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
))
601 did_something
= true;
602 if (!children
[1]->range_valid
)
603 log_file_error(filename
, location
.first_line
, "Non-constant width range on enum item decl.\n");
604 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
610 case AST_TO_UNSIGNED
:
617 case AST_REDUCE_XNOR
:
618 case AST_REDUCE_BOOL
:
619 detect_width_simple
= true;
620 children_are_self_determined
= true;
635 detect_width_simple
= true;
639 case AST_SHIFT_RIGHT
:
640 case AST_SHIFT_SLEFT
:
641 case AST_SHIFT_SRIGHT
:
643 detect_width_simple
= true;
644 child_1_is_self_determined
= true;
657 for (auto child
: children
) {
658 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
659 did_something
= true;
660 child
->detectSignWidthWorker(width_hint
, sign_hint
);
662 reset_width_after_children
= true;
668 detect_width_simple
= true;
669 children_are_self_determined
= true;
673 detect_width_simple
= true;
674 child_0_is_self_determined
= true;
678 detect_width_simple
= true;
679 children_are_self_determined
= true;
684 children_are_self_determined
= true;
692 if (detect_width_simple
&& width_hint
< 0) {
693 if (type
== AST_REPLICATE
)
694 while (children
[0]->simplify(true, false, in_lvalue
, stage
, -1, false, true) == true)
695 did_something
= true;
696 for (auto child
: children
)
697 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
698 did_something
= true;
699 detectSignWidth(width_hint
, sign_hint
);
702 if (type
== AST_FCALL
&& str
== "\\$past")
703 detectSignWidth(width_hint
, sign_hint
);
705 if (type
== AST_TERNARY
) {
706 int width_hint_left
, width_hint_right
;
707 bool sign_hint_left
, sign_hint_right
;
708 bool found_real_left
, found_real_right
;
709 children
[1]->detectSignWidth(width_hint_left
, sign_hint_left
, &found_real_left
);
710 children
[2]->detectSignWidth(width_hint_right
, sign_hint_right
, &found_real_right
);
711 if (found_real_left
|| found_real_right
) {
712 child_1_is_self_determined
= true;
713 child_2_is_self_determined
= true;
717 if (type
== AST_CONDX
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
718 for (auto &bit
: children
.at(0)->bits
)
719 if (bit
== State::Sz
|| bit
== State::Sx
)
723 if (type
== AST_CONDZ
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
724 for (auto &bit
: children
.at(0)->bits
)
725 if (bit
== State::Sz
)
729 if (const_fold
&& type
== AST_CASE
)
731 while (children
[0]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
732 if (children
[0]->type
== AST_CONSTANT
&& children
[0]->bits_only_01()) {
733 std::vector
<AstNode
*> new_children
;
734 new_children
.push_back(children
[0]);
735 for (int i
= 1; i
< GetSize(children
); i
++) {
736 AstNode
*child
= children
[i
];
737 log_assert(child
->type
== AST_COND
|| child
->type
== AST_CONDX
|| child
->type
== AST_CONDZ
);
738 for (auto v
: child
->children
) {
739 if (v
->type
== AST_DEFAULT
)
740 goto keep_const_cond
;
741 if (v
->type
== AST_BLOCK
)
743 while (v
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
744 if (v
->type
== AST_CONSTANT
&& v
->bits_only_01()) {
745 if (v
->bits
== children
[0]->bits
) {
746 while (i
+1 < GetSize(children
))
747 delete children
[++i
];
748 goto keep_const_cond
;
752 goto keep_const_cond
;
756 new_children
.push_back(child
);
760 new_children
.swap(children
);
764 // simplify all children first
765 // (iterate by index as e.g. auto wires can add new children in the process)
766 for (size_t i
= 0; i
< children
.size(); i
++) {
767 bool did_something_here
= true;
768 bool backup_flag_autowire
= flag_autowire
;
769 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && i
>= 3)
771 if ((type
== AST_GENIF
|| type
== AST_GENCASE
) && i
>= 1)
773 if (type
== AST_GENBLOCK
)
775 if (type
== AST_BLOCK
&& !str
.empty())
777 if (type
== AST_PREFIX
&& i
>= 1)
779 if (type
== AST_DEFPARAM
&& i
== 0)
780 flag_autowire
= true;
781 while (did_something_here
&& i
< children
.size()) {
782 bool const_fold_here
= const_fold
, in_lvalue_here
= in_lvalue
;
783 int width_hint_here
= width_hint
;
784 bool sign_hint_here
= sign_hint
;
785 bool in_param_here
= in_param
;
786 if (i
== 0 && (type
== AST_REPLICATE
|| type
== AST_WIRE
))
787 const_fold_here
= true, in_param_here
= true;
788 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
)
789 const_fold_here
= true;
790 if (i
== 0 && (type
== AST_ASSIGN
|| type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
))
791 in_lvalue_here
= true;
792 if (type
== AST_BLOCK
) {
793 current_block
= this;
794 current_block_child
= children
[i
];
796 if ((type
== AST_ALWAYS
|| type
== AST_INITIAL
) && children
[i
]->type
== AST_BLOCK
)
797 current_top_block
= children
[i
];
798 if (i
== 0 && child_0_is_self_determined
)
799 width_hint_here
= -1, sign_hint_here
= false;
800 if (i
== 1 && child_1_is_self_determined
)
801 width_hint_here
= -1, sign_hint_here
= false;
802 if (i
== 2 && child_2_is_self_determined
)
803 width_hint_here
= -1, sign_hint_here
= false;
804 if (children_are_self_determined
)
805 width_hint_here
= -1, sign_hint_here
= false;
806 did_something_here
= children
[i
]->simplify(const_fold_here
, at_zero
, in_lvalue_here
, stage
, width_hint_here
, sign_hint_here
, in_param_here
);
807 if (did_something_here
)
808 did_something
= true;
810 if (stage
== 2 && children
[i
]->type
== AST_INITIAL
&& current_ast_mod
!= this) {
811 current_ast_mod
->children
.push_back(children
[i
]);
812 children
.erase(children
.begin() + (i
--));
813 did_something
= true;
815 flag_autowire
= backup_flag_autowire
;
817 for (auto &attr
: attributes
) {
818 while (attr
.second
->simplify(true, false, false, stage
, -1, false, true))
819 did_something
= true;
822 if (reset_width_after_children
) {
823 width_hint
= backup_width_hint
;
824 sign_hint
= backup_sign_hint
;
826 detectSignWidth(width_hint
, sign_hint
);
829 current_block
= backup_current_block
;
830 current_block_child
= backup_current_block_child
;
831 current_top_block
= backup_current_top_block
;
832 current_always
= backup_current_always
;
833 current_always_clocked
= backup_current_always_clocked
;
835 for (auto it
= backup_scope
.begin(); it
!= backup_scope
.end(); it
++) {
836 if (it
->second
== NULL
)
837 current_scope
.erase(it
->first
);
839 current_scope
[it
->first
] = it
->second
;
842 current_filename
= filename
;
844 if (type
== AST_MODULE
)
845 current_scope
.clear();
847 // convert defparam nodes to cell parameters
848 if (type
== AST_DEFPARAM
&& !children
.empty())
850 if (children
[0]->type
!= AST_IDENTIFIER
)
851 log_file_error(filename
, location
.first_line
, "Module name in defparam contains non-constant expressions!\n");
853 string modname
, paramname
= children
[0]->str
;
855 size_t pos
= paramname
.rfind('.');
857 while (pos
!= 0 && pos
!= std::string::npos
)
859 modname
= paramname
.substr(0, pos
);
861 if (current_scope
.count(modname
))
864 pos
= paramname
.rfind('.', pos
- 1);
867 if (pos
== std::string::npos
)
868 log_file_error(filename
, location
.first_line
, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname
).c_str());
870 paramname
= "\\" + paramname
.substr(pos
+1);
872 if (current_scope
.at(modname
)->type
!= AST_CELL
)
873 log_file_error(filename
, location
.first_line
, "Defparam argument `%s . %s` does not match a cell!\n",
874 RTLIL::unescape_id(modname
).c_str(), RTLIL::unescape_id(paramname
).c_str());
876 AstNode
*paraset
= new AstNode(AST_PARASET
, children
[1]->clone(), GetSize(children
) > 2 ? children
[2]->clone() : NULL
);
877 paraset
->str
= paramname
;
879 AstNode
*cell
= current_scope
.at(modname
);
880 cell
->children
.insert(cell
->children
.begin() + 1, paraset
);
885 if (type
== AST_TYPEDEF
) {
886 log_assert(children
.size() == 1);
887 log_assert(children
[0]->type
== AST_WIRE
|| children
[0]->type
== AST_MEMORY
);
888 while(children
[0]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
))
889 did_something
= true;
890 log_assert(!children
[0]->is_custom_type
);
893 // resolve types of wires
894 if (type
== AST_WIRE
|| type
== AST_MEMORY
) {
895 if (is_custom_type
) {
896 log_assert(children
.size() >= 1);
897 log_assert(children
[0]->type
== AST_WIRETYPE
);
898 if (!current_scope
.count(children
[0]->str
))
899 log_file_error(filename
, location
.first_line
, "Unknown identifier `%s' used as type name\n", children
[0]->str
.c_str());
900 AstNode
*resolved_type
= current_scope
.at(children
[0]->str
);
901 if (resolved_type
->type
!= AST_TYPEDEF
)
902 log_file_error(filename
, location
.first_line
, "`%s' does not name a type\n", children
[0]->str
.c_str());
903 log_assert(resolved_type
->children
.size() == 1);
904 AstNode
*templ
= resolved_type
->children
[0];
905 // Remove type reference
907 children
.erase(children
.begin());
909 // Ensure typedef itself is fully simplified
910 while(templ
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
912 if (type
== AST_WIRE
)
914 is_reg
= templ
->is_reg
;
915 is_logic
= templ
->is_logic
;
916 is_signed
= templ
->is_signed
;
917 is_string
= templ
->is_string
;
918 is_custom_type
= templ
->is_custom_type
;
920 range_valid
= templ
->range_valid
;
921 range_swapped
= templ
->range_swapped
;
922 range_left
= templ
->range_left
;
923 range_right
= templ
->range_right
;
924 attributes
[ID::wiretype
] = mkconst_str(resolved_type
->str
);
926 if (templ
->attributes
.count(ID::enum_type
)){
927 //get reference to enum node:
928 const std::string
&enum_type
= templ
->attributes
[ID::enum_type
]->str
;
929 // log("enum_type=%s (count=%lu)\n", enum_type.c_str(), current_scope.count(enum_type));
930 // log("current scope:\n");
931 // for (auto &it : current_scope)
932 // log(" %s\n", it.first.c_str());
933 log_assert(current_scope
.count(enum_type
) == 1);
934 AstNode
*enum_node
= current_scope
.at(enum_type
);
935 log_assert(enum_node
->type
== AST_ENUM
);
936 //get width from 1st enum item:
937 log_assert(enum_node
->children
.size() >= 1);
938 AstNode
*enum_item0
= enum_node
->children
[0];
939 log_assert(enum_item0
->type
== AST_ENUM_ITEM
);
941 if (!enum_item0
->range_valid
)
943 else if (enum_item0
->range_swapped
)
944 width
= enum_item0
->range_right
- enum_item0
->range_left
+ 1;
946 width
= enum_item0
->range_left
- enum_item0
->range_right
+ 1;
947 log_assert(width
> 0);
948 //add declared enum items:
949 for (auto enum_item
: enum_node
->children
){
950 log_assert(enum_item
->type
== AST_ENUM_ITEM
);
953 if (enum_item
->children
.size() == 1){
955 } else if (enum_item
->children
.size() == 2){
956 log_assert(enum_item
->children
[1]->type
== AST_RANGE
);
957 is_signed
= enum_item
->children
[1]->is_signed
;
959 log_error("enum_item children size==%lu, expected 1 or 2 for %s (%s)\n",
960 enum_item
->children
.size(),
961 enum_item
->str
.c_str(), enum_node
->str
.c_str()
964 //start building attribute string
965 std::string enum_item_str
= "\\enum_value_";
966 //get enum item value
967 if(enum_item
->children
[0]->type
!= AST_CONSTANT
){
968 log_error("expected const, got %s for %s (%s)\n",
969 type2str(enum_item
->children
[0]->type
).c_str(),
970 enum_item
->str
.c_str(), enum_node
->str
.c_str()
973 RTLIL::Const val
= enum_item
->children
[0]->bitsAsConst(width
, is_signed
);
974 enum_item_str
.append(val
.as_string());
975 //set attribute for available val to enum item name mappings
976 attributes
[enum_item_str
] = mkconst_str(enum_item
->str
);
980 // Insert clones children from template at beginning
981 for (int i
= 0; i
< GetSize(templ
->children
); i
++)
982 children
.insert(children
.begin() + i
, templ
->children
[i
]->clone());
984 if (type
== AST_MEMORY
&& GetSize(children
) == 1) {
985 // Single-bit memories must have [0:0] range
986 AstNode
*rng
= new AstNode(AST_RANGE
);
987 rng
->children
.push_back(AstNode::mkconst_int(0, true));
988 rng
->children
.push_back(AstNode::mkconst_int(0, true));
989 children
.insert(children
.begin(), rng
);
992 did_something
= true;
994 log_assert(!is_custom_type
);
997 // resolve types of parameters
998 if (type
== AST_LOCALPARAM
|| type
== AST_PARAMETER
) {
999 if (is_custom_type
) {
1000 log_assert(children
.size() == 2);
1001 log_assert(children
[1]->type
== AST_WIRETYPE
);
1002 if (!current_scope
.count(children
[1]->str
))
1003 log_file_error(filename
, location
.first_line
, "Unknown identifier `%s' used as type name\n", children
[1]->str
.c_str());
1004 AstNode
*resolved_type
= current_scope
.at(children
[1]->str
);
1005 if (resolved_type
->type
!= AST_TYPEDEF
)
1006 log_file_error(filename
, location
.first_line
, "`%s' does not name a type\n", children
[1]->str
.c_str());
1007 log_assert(resolved_type
->children
.size() == 1);
1008 AstNode
*templ
= resolved_type
->children
[0];
1010 children
.pop_back();
1012 // Ensure typedef itself is fully simplified
1013 while(templ
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
1015 if (templ
->type
== AST_MEMORY
)
1016 log_file_error(filename
, location
.first_line
, "unpacked array type `%s' cannot be used for a parameter\n", children
[1]->str
.c_str());
1017 is_signed
= templ
->is_signed
;
1018 is_string
= templ
->is_string
;
1019 is_custom_type
= templ
->is_custom_type
;
1021 range_valid
= templ
->range_valid
;
1022 range_swapped
= templ
->range_swapped
;
1023 range_left
= templ
->range_left
;
1024 range_right
= templ
->range_right
;
1025 attributes
[ID::wiretype
] = mkconst_str(resolved_type
->str
);
1026 for (auto template_child
: templ
->children
)
1027 children
.push_back(template_child
->clone());
1028 did_something
= true;
1030 log_assert(!is_custom_type
);
1033 // resolve constant prefixes
1034 if (type
== AST_PREFIX
) {
1035 if (children
[0]->type
!= AST_CONSTANT
) {
1036 // dumpAst(NULL, "> ");
1037 log_file_error(filename
, location
.first_line
, "Index in generate block prefix syntax is not constant!\n");
1039 if (children
[1]->type
== AST_PREFIX
)
1040 children
[1]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
);
1041 log_assert(children
[1]->type
== AST_IDENTIFIER
);
1042 newNode
= children
[1]->clone();
1043 const char *second_part
= children
[1]->str
.c_str();
1044 if (second_part
[0] == '\\')
1046 newNode
->str
= stringf("%s[%d].%s", str
.c_str(), children
[0]->integer
, second_part
);
1050 // evaluate TO_BITS nodes
1051 if (type
== AST_TO_BITS
) {
1052 if (children
[0]->type
!= AST_CONSTANT
)
1053 log_file_error(filename
, location
.first_line
, "Left operand of to_bits expression is not constant!\n");
1054 if (children
[1]->type
!= AST_CONSTANT
)
1055 log_file_error(filename
, location
.first_line
, "Right operand of to_bits expression is not constant!\n");
1056 RTLIL::Const new_value
= children
[1]->bitsAsConst(children
[0]->bitsAsConst().as_int(), children
[1]->is_signed
);
1057 newNode
= mkconst_bits(new_value
.bits
, children
[1]->is_signed
);
1061 // annotate constant ranges
1062 if (type
== AST_RANGE
) {
1063 bool old_range_valid
= range_valid
;
1064 range_valid
= false;
1065 range_swapped
= false;
1068 log_assert(children
.size() >= 1);
1069 if (children
[0]->type
== AST_CONSTANT
) {
1071 range_left
= children
[0]->integer
;
1072 if (children
.size() == 1)
1073 range_right
= range_left
;
1075 if (children
.size() >= 2) {
1076 if (children
[1]->type
== AST_CONSTANT
)
1077 range_right
= children
[1]->integer
;
1079 range_valid
= false;
1081 if (old_range_valid
!= range_valid
)
1082 did_something
= true;
1083 if (range_valid
&& range_right
> range_left
) {
1084 int tmp
= range_right
;
1085 range_right
= range_left
;
1087 range_swapped
= true;
1091 // annotate wires with their ranges
1092 if (type
== AST_WIRE
) {
1093 if (children
.size() > 0) {
1094 if (children
[0]->range_valid
) {
1096 did_something
= true;
1098 range_swapped
= children
[0]->range_swapped
;
1099 range_left
= children
[0]->range_left
;
1100 range_right
= children
[0]->range_right
;
1101 bool force_upto
= false, force_downto
= false;
1102 if (attributes
.count(ID::force_upto
)) {
1103 AstNode
*val
= attributes
[ID::force_upto
];
1104 if (val
->type
!= AST_CONSTANT
)
1105 log_file_error(filename
, location
.first_line
, "Attribute `force_upto' with non-constant value!\n");
1106 force_upto
= val
->asAttrConst().as_bool();
1108 if (attributes
.count(ID::force_downto
)) {
1109 AstNode
*val
= attributes
[ID::force_downto
];
1110 if (val
->type
!= AST_CONSTANT
)
1111 log_file_error(filename
, location
.first_line
, "Attribute `force_downto' with non-constant value!\n");
1112 force_downto
= val
->asAttrConst().as_bool();
1114 if (force_upto
&& force_downto
)
1115 log_file_error(filename
, location
.first_line
, "Attributes `force_downto' and `force_upto' cannot be both set!\n");
1116 if ((force_upto
&& !range_swapped
) || (force_downto
&& range_swapped
)) {
1117 std::swap(range_left
, range_right
);
1118 range_swapped
= force_upto
;
1123 did_something
= true;
1125 range_swapped
= false;
1131 // resolve multiranges on memory decl
1132 if (type
== AST_MEMORY
&& children
.size() > 1 && children
[1]->type
== AST_MULTIRANGE
)
1135 multirange_dimensions
.clear();
1136 for (auto range
: children
[1]->children
) {
1137 if (!range
->range_valid
)
1138 log_file_error(filename
, location
.first_line
, "Non-constant range on memory decl.\n");
1139 multirange_dimensions
.push_back(min(range
->range_left
, range
->range_right
));
1140 multirange_dimensions
.push_back(max(range
->range_left
, range
->range_right
) - min(range
->range_left
, range
->range_right
) + 1);
1141 total_size
*= multirange_dimensions
.back();
1144 children
[1] = new AstNode(AST_RANGE
, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size
-1, true));
1145 did_something
= true;
1148 // resolve multiranges on memory access
1149 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
&& children
.size() > 0 && children
[0]->type
== AST_MULTIRANGE
)
1151 AstNode
*index_expr
= nullptr;
1153 for (int i
= 0; 2*i
< GetSize(id2ast
->multirange_dimensions
); i
++)
1155 if (GetSize(children
[0]->children
) < i
)
1156 log_file_error(filename
, location
.first_line
, "Insufficient number of array indices for %s.\n", log_id(str
));
1158 AstNode
*new_index_expr
= children
[0]->children
[i
]->children
.at(0)->clone();
1160 if (id2ast
->multirange_dimensions
[2*i
])
1161 new_index_expr
= new AstNode(AST_SUB
, new_index_expr
, AstNode::mkconst_int(id2ast
->multirange_dimensions
[2*i
], true));
1164 index_expr
= new_index_expr
;
1166 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
);
1169 for (int i
= GetSize(id2ast
->multirange_dimensions
)/2; i
< GetSize(children
[0]->children
); i
++)
1170 children
.push_back(children
[0]->children
[i
]->clone());
1173 if (index_expr
== nullptr)
1174 children
.erase(children
.begin());
1176 children
[0] = new AstNode(AST_RANGE
, index_expr
);
1178 did_something
= true;
1181 // trim/extend parameters
1182 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_ENUM_ITEM
) {
1183 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
1184 if (!children
[1]->range_valid
)
1185 log_file_error(filename
, location
.first_line
, "Non-constant width range on parameter decl.\n");
1186 int width
= std::abs(children
[1]->range_left
- children
[1]->range_right
) + 1;
1187 if (children
[0]->type
== AST_REALVALUE
) {
1188 RTLIL::Const constvalue
= children
[0]->realAsConst(width
);
1189 log_file_warning(filename
, location
.first_line
, "converting real value %e to binary %s.\n",
1190 children
[0]->realvalue
, log_signal(constvalue
));
1192 children
[0] = mkconst_bits(constvalue
.bits
, sign_hint
);
1193 did_something
= true;
1195 if (children
[0]->type
== AST_CONSTANT
) {
1196 if (width
!= int(children
[0]->bits
.size())) {
1197 RTLIL::SigSpec
sig(children
[0]->bits
);
1198 sig
.extend_u0(width
, children
[0]->is_signed
);
1199 AstNode
*old_child_0
= children
[0];
1200 children
[0] = mkconst_bits(sig
.as_const().bits
, is_signed
);
1203 children
[0]->is_signed
= is_signed
;
1206 range_swapped
= children
[1]->range_swapped
;
1207 range_left
= children
[1]->range_left
;
1208 range_right
= children
[1]->range_right
;
1210 if (children
.size() > 1 && children
[1]->type
== AST_REALVALUE
&& children
[0]->type
== AST_CONSTANT
) {
1211 double as_realvalue
= children
[0]->asReal(sign_hint
);
1213 children
[0] = new AstNode(AST_REALVALUE
);
1214 children
[0]->realvalue
= as_realvalue
;
1215 did_something
= true;
1219 // annotate identifiers using scope resolution and create auto-wires as needed
1220 if (type
== AST_IDENTIFIER
) {
1221 if (current_scope
.count(str
) == 0) {
1222 AstNode
*current_scope_ast
= (current_ast_mod
== nullptr) ? current_ast
: current_ast_mod
;
1223 for (auto node
: current_scope_ast
->children
) {
1224 //log("looking at mod scope child %s\n", type2str(node->type).c_str());
1225 switch (node
->type
) {
1227 case AST_LOCALPARAM
:
1234 case AST_DPI_FUNCTION
:
1235 //log("found child %s, %s\n", type2str(node->type).c_str(), node->str.c_str());
1236 if (str
== node
->str
) {
1237 //log("add %s, type %s to scope\n", str.c_str(), type2str(node->type).c_str());
1238 current_scope
[node
->str
] = node
;
1242 current_scope
[node
->str
] = node
;
1243 for (auto enum_node
: node
->children
) {
1244 log_assert(enum_node
->type
==AST_ENUM_ITEM
);
1245 if (str
== enum_node
->str
) {
1246 //log("\nadding enum item %s to scope\n", str.c_str());
1247 current_scope
[str
] = enum_node
;
1256 if (current_scope
.count(str
) == 0) {
1257 if (current_ast_mod
== nullptr) {
1258 log_file_error(filename
, location
.first_line
, "Identifier `%s' is implicitly declared outside of a module.\n", str
.c_str());
1259 } else if (flag_autowire
|| str
== "\\$global_clock") {
1260 AstNode
*auto_wire
= new AstNode(AST_AUTOWIRE
);
1261 auto_wire
->str
= str
;
1262 current_ast_mod
->children
.push_back(auto_wire
);
1263 current_scope
[str
] = auto_wire
;
1264 did_something
= true;
1266 log_file_error(filename
, location
.first_line
, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str
.c_str());
1269 if (id2ast
!= current_scope
[str
]) {
1270 id2ast
= current_scope
[str
];
1271 did_something
= true;
1275 // split memory access with bit select to individual statements
1276 if (type
== AST_IDENTIFIER
&& children
.size() == 2 && children
[0]->type
== AST_RANGE
&& children
[1]->type
== AST_RANGE
&& !in_lvalue
)
1278 if (id2ast
== NULL
|| id2ast
->type
!= AST_MEMORY
|| children
[0]->children
.size() != 1)
1279 log_file_error(filename
, location
.first_line
, "Invalid bit-select on memory access!\n");
1281 int mem_width
, mem_size
, addr_bits
;
1282 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
1284 int data_range_left
= id2ast
->children
[0]->range_left
;
1285 int data_range_right
= id2ast
->children
[0]->range_right
;
1287 if (id2ast
->children
[0]->range_swapped
)
1288 std::swap(data_range_left
, data_range_right
);
1290 std::stringstream sstr
;
1291 sstr
<< "$mem2bits$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
1292 std::string wire_id
= sstr
.str();
1294 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
1295 wire
->str
= wire_id
;
1297 wire
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
1298 current_ast_mod
->children
.push_back(wire
);
1299 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
1301 AstNode
*data
= clone();
1302 delete data
->children
[1];
1303 data
->children
.pop_back();
1305 AstNode
*assign
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), data
);
1306 assign
->children
[0]->str
= wire_id
;
1307 assign
->children
[0]->was_checked
= true;
1311 size_t assign_idx
= 0;
1312 while (assign_idx
< current_block
->children
.size() && current_block
->children
[assign_idx
] != current_block_child
)
1314 log_assert(assign_idx
< current_block
->children
.size());
1315 current_block
->children
.insert(current_block
->children
.begin()+assign_idx
, assign
);
1316 wire
->is_reg
= true;
1320 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
1321 proc
->children
[0]->children
.push_back(assign
);
1322 current_ast_mod
->children
.push_back(proc
);
1325 newNode
= new AstNode(AST_IDENTIFIER
, children
[1]->clone());
1326 newNode
->str
= wire_id
;
1327 newNode
->id2ast
= wire
;
1331 if (type
== AST_WHILE
)
1332 log_file_error(filename
, location
.first_line
, "While loops are only allowed in constant functions!\n");
1334 if (type
== AST_REPEAT
)
1336 AstNode
*count
= children
[0];
1337 AstNode
*body
= children
[1];
1339 // eval count expression
1340 while (count
->simplify(true, false, false, stage
, 32, true, false)) { }
1342 if (count
->type
!= AST_CONSTANT
)
1343 log_file_error(filename
, location
.first_line
, "Repeat loops outside must have constant repeat counts!\n");
1345 // convert to a block with the body repeated n times
1348 for (int i
= 0; i
< count
->bitsAsConst().as_int(); i
++)
1349 children
.insert(children
.begin(), body
->clone());
1353 did_something
= true;
1356 // unroll for loops and generate-for blocks
1357 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && children
.size() != 0)
1359 AstNode
*init_ast
= children
[0];
1360 AstNode
*while_ast
= children
[1];
1361 AstNode
*next_ast
= children
[2];
1362 AstNode
*body_ast
= children
[3];
1364 while (body_ast
->type
== AST_GENBLOCK
&& body_ast
->str
.empty() &&
1365 body_ast
->children
.size() == 1 && body_ast
->children
.at(0)->type
== AST_GENBLOCK
)
1366 body_ast
= body_ast
->children
.at(0);
1368 if (init_ast
->type
!= AST_ASSIGN_EQ
)
1369 log_file_error(filename
, location
.first_line
, "Unsupported 1st expression of generate for-loop!\n");
1370 if (next_ast
->type
!= AST_ASSIGN_EQ
)
1371 log_file_error(filename
, location
.first_line
, "Unsupported 3rd expression of generate for-loop!\n");
1373 if (type
== AST_GENFOR
) {
1374 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
1375 log_file_error(filename
, location
.first_line
, "Left hand side of 1st expression of generate for-loop is not a gen var!\n");
1376 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
1377 log_file_error(filename
, location
.first_line
, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n");
1379 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1380 log_file_error(filename
, location
.first_line
, "Left hand side of 1st expression of generate for-loop is not a register!\n");
1381 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1382 log_file_error(filename
, location
.first_line
, "Left hand side of 3rd expression of generate for-loop is not a register!\n");
1385 if (init_ast
->children
[0]->id2ast
!= next_ast
->children
[0]->id2ast
)
1386 log_file_error(filename
, location
.first_line
, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n");
1388 // eval 1st expression
1389 AstNode
*varbuf
= init_ast
->children
[1]->clone();
1391 int expr_width_hint
= -1;
1392 bool expr_sign_hint
= true;
1393 varbuf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1394 while (varbuf
->simplify(true, false, false, stage
, 32, true, false)) { }
1397 if (varbuf
->type
!= AST_CONSTANT
)
1398 log_file_error(filename
, location
.first_line
, "Right hand side of 1st expression of generate for-loop is not constant!\n");
1400 auto resolved
= current_scope
.at(init_ast
->children
[0]->str
);
1401 if (resolved
->range_valid
) {
1402 int const_size
= varbuf
->range_left
- varbuf
->range_right
;
1403 int resolved_size
= resolved
->range_left
- resolved
->range_right
;
1404 if (const_size
< resolved_size
) {
1405 for (int i
= const_size
; i
< resolved_size
; i
++)
1406 varbuf
->bits
.push_back(resolved
->is_signed
? varbuf
->bits
.back() : State::S0
);
1407 varbuf
->range_left
= resolved
->range_left
;
1408 varbuf
->range_right
= resolved
->range_right
;
1409 varbuf
->range_swapped
= resolved
->range_swapped
;
1410 varbuf
->range_valid
= resolved
->range_valid
;
1414 varbuf
= new AstNode(AST_LOCALPARAM
, varbuf
);
1415 varbuf
->str
= init_ast
->children
[0]->str
;
1417 AstNode
*backup_scope_varbuf
= current_scope
[varbuf
->str
];
1418 current_scope
[varbuf
->str
] = varbuf
;
1420 size_t current_block_idx
= 0;
1421 if (type
== AST_FOR
) {
1422 while (current_block_idx
< current_block
->children
.size() &&
1423 current_block
->children
[current_block_idx
] != current_block_child
)
1424 current_block_idx
++;
1429 // eval 2nd expression
1430 AstNode
*buf
= while_ast
->clone();
1432 int expr_width_hint
= -1;
1433 bool expr_sign_hint
= true;
1434 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1435 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, false)) { }
1438 if (buf
->type
!= AST_CONSTANT
)
1439 log_file_error(filename
, location
.first_line
, "2nd expression of generate for-loop is not constant!\n");
1441 if (buf
->integer
== 0) {
1448 int index
= varbuf
->children
[0]->integer
;
1449 if (body_ast
->type
== AST_GENBLOCK
)
1450 buf
= body_ast
->clone();
1452 buf
= new AstNode(AST_GENBLOCK
, body_ast
->clone());
1453 if (buf
->str
.empty()) {
1454 std::stringstream sstr
;
1455 sstr
<< "$genblock$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
1456 buf
->str
= sstr
.str();
1458 std::map
<std::string
, std::string
> name_map
;
1459 std::stringstream sstr
;
1460 sstr
<< buf
->str
<< "[" << index
<< "].";
1461 buf
->expand_genblock(varbuf
->str
, sstr
.str(), name_map
);
1463 if (type
== AST_GENFOR
) {
1464 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1465 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1466 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1469 for (size_t i
= 0; i
< buf
->children
.size(); i
++)
1470 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
->children
[i
]);
1472 buf
->children
.clear();
1475 // eval 3rd expression
1476 buf
= next_ast
->children
[1]->clone();
1478 int expr_width_hint
= -1;
1479 bool expr_sign_hint
= true;
1480 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1481 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, true)) { }
1484 if (buf
->type
!= AST_CONSTANT
)
1485 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());
1487 delete varbuf
->children
[0];
1488 varbuf
->children
[0] = buf
;
1491 if (type
== AST_FOR
) {
1492 AstNode
*buf
= next_ast
->clone();
1493 delete buf
->children
[1];
1494 buf
->children
[1] = varbuf
->children
[0]->clone();
1495 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
);
1498 current_scope
[varbuf
->str
] = backup_scope_varbuf
;
1501 did_something
= true;
1504 // check for local objects in unnamed block
1505 if (type
== AST_BLOCK
&& str
.empty())
1507 for (size_t i
= 0; i
< children
.size(); i
++)
1508 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
)
1509 log_file_error(children
[i
]->filename
, children
[i
]->location
.first_line
, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
1512 // transform block with name
1513 if (type
== AST_BLOCK
&& !str
.empty())
1515 std::map
<std::string
, std::string
> name_map
;
1516 expand_genblock(std::string(), str
+ ".", name_map
);
1518 std::vector
<AstNode
*> new_children
;
1519 for (size_t i
= 0; i
< children
.size(); i
++)
1520 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
) {
1521 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1522 current_ast_mod
->children
.push_back(children
[i
]);
1523 current_scope
[children
[i
]->str
] = children
[i
];
1525 new_children
.push_back(children
[i
]);
1527 children
.swap(new_children
);
1528 did_something
= true;
1532 // simplify unconditional generate block
1533 if (type
== AST_GENBLOCK
&& children
.size() != 0)
1536 std::map
<std::string
, std::string
> name_map
;
1537 expand_genblock(std::string(), str
+ ".", name_map
);
1540 for (size_t i
= 0; i
< children
.size(); i
++) {
1541 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1542 current_ast_mod
->children
.push_back(children
[i
]);
1546 did_something
= true;
1549 // simplify generate-if blocks
1550 if (type
== AST_GENIF
&& children
.size() != 0)
1552 AstNode
*buf
= children
[0]->clone();
1553 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1554 if (buf
->type
!= AST_CONSTANT
) {
1555 // for (auto f : log_files)
1556 // dumpAst(f, "verilog-ast> ");
1557 log_file_error(filename
, location
.first_line
, "Condition for generate if is not constant!\n");
1559 if (buf
->asBool() != 0) {
1561 buf
= children
[1]->clone();
1564 buf
= children
.size() > 2 ? children
[2]->clone() : NULL
;
1569 if (buf
->type
!= AST_GENBLOCK
)
1570 buf
= new AstNode(AST_GENBLOCK
, buf
);
1572 if (!buf
->str
.empty()) {
1573 std::map
<std::string
, std::string
> name_map
;
1574 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
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 buf
->children
.clear();
1587 did_something
= true;
1590 // simplify generate-case blocks
1591 if (type
== AST_GENCASE
&& children
.size() != 0)
1593 AstNode
*buf
= children
[0]->clone();
1594 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1595 if (buf
->type
!= AST_CONSTANT
) {
1596 // for (auto f : log_files)
1597 // dumpAst(f, "verilog-ast> ");
1598 log_file_error(filename
, location
.first_line
, "Condition for generate case is not constant!\n");
1601 bool ref_signed
= buf
->is_signed
;
1602 RTLIL::Const ref_value
= buf
->bitsAsConst();
1605 AstNode
*selected_case
= NULL
;
1606 for (size_t i
= 1; i
< children
.size(); i
++)
1608 log_assert(children
.at(i
)->type
== AST_COND
|| children
.at(i
)->type
== AST_CONDX
|| children
.at(i
)->type
== AST_CONDZ
);
1610 AstNode
*this_genblock
= NULL
;
1611 for (auto child
: children
.at(i
)->children
) {
1612 log_assert(this_genblock
== NULL
);
1613 if (child
->type
== AST_GENBLOCK
)
1614 this_genblock
= child
;
1617 for (auto child
: children
.at(i
)->children
)
1619 if (child
->type
== AST_DEFAULT
) {
1620 if (selected_case
== NULL
)
1621 selected_case
= this_genblock
;
1624 if (child
->type
== AST_GENBLOCK
)
1627 buf
= child
->clone();
1628 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1629 if (buf
->type
!= AST_CONSTANT
) {
1630 // for (auto f : log_files)
1631 // dumpAst(f, "verilog-ast> ");
1632 log_file_error(filename
, location
.first_line
, "Expression in generate case is not constant!\n");
1635 bool is_selected
= RTLIL::const_eq(ref_value
, buf
->bitsAsConst(), ref_signed
&& buf
->is_signed
, ref_signed
&& buf
->is_signed
, 1).as_bool();
1639 selected_case
= this_genblock
;
1640 i
= children
.size();
1646 if (selected_case
!= NULL
)
1648 log_assert(selected_case
->type
== AST_GENBLOCK
);
1649 buf
= selected_case
->clone();
1651 if (!buf
->str
.empty()) {
1652 std::map
<std::string
, std::string
> name_map
;
1653 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1656 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1657 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1658 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1661 buf
->children
.clear();
1666 did_something
= true;
1669 // unroll cell arrays
1670 if (type
== AST_CELLARRAY
)
1672 if (!children
.at(0)->range_valid
)
1673 log_file_error(filename
, location
.first_line
, "Non-constant array range on cell array.\n");
1675 newNode
= new AstNode(AST_GENBLOCK
);
1676 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;
1678 for (int i
= 0; i
< num
; i
++) {
1679 int idx
= children
.at(0)->range_left
> children
.at(0)->range_right
? children
.at(0)->range_right
+ i
: children
.at(0)->range_right
- i
;
1680 AstNode
*new_cell
= children
.at(1)->clone();
1681 newNode
->children
.push_back(new_cell
);
1682 new_cell
->str
+= stringf("[%d]", idx
);
1683 if (new_cell
->type
== AST_PRIMITIVE
) {
1684 log_file_error(filename
, location
.first_line
, "Cell arrays of primitives are currently not supported.\n");
1686 log_assert(new_cell
->children
.at(0)->type
== AST_CELLTYPE
);
1687 new_cell
->children
.at(0)->str
= stringf("$array:%d:%d:%s", i
, num
, new_cell
->children
.at(0)->str
.c_str());
1694 // replace primitives with assignments
1695 if (type
== AST_PRIMITIVE
)
1697 if (children
.size() < 2)
1698 log_file_error(filename
, location
.first_line
, "Insufficient number of arguments for primitive `%s'!\n", str
.c_str());
1700 std::vector
<AstNode
*> children_list
;
1701 for (auto child
: children
) {
1702 log_assert(child
->type
== AST_ARGUMENT
);
1703 log_assert(child
->children
.size() == 1);
1704 children_list
.push_back(child
->children
[0]);
1705 child
->children
.clear();
1710 if (str
== "bufif0" || str
== "bufif1" || str
== "notif0" || str
== "notif1")
1712 if (children_list
.size() != 3)
1713 log_file_error(filename
, location
.first_line
, "Invalid number of arguments for primitive `%s'!\n", str
.c_str());
1715 std::vector
<RTLIL::State
> z_const(1, RTLIL::State::Sz
);
1717 AstNode
*mux_input
= children_list
.at(1);
1718 if (str
== "notif0" || str
== "notif1") {
1719 mux_input
= new AstNode(AST_BIT_NOT
, mux_input
);
1721 AstNode
*node
= new AstNode(AST_TERNARY
, children_list
.at(2));
1722 if (str
== "bufif0") {
1723 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1724 node
->children
.push_back(mux_input
);
1726 node
->children
.push_back(mux_input
);
1727 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1732 children
.push_back(children_list
.at(0));
1733 children
.back()->was_checked
= true;
1734 children
.push_back(node
);
1735 did_something
= true;
1739 AstNodeType op_type
= AST_NONE
;
1740 bool invert_results
= false;
1743 op_type
= AST_BIT_AND
;
1745 op_type
= AST_BIT_AND
, invert_results
= true;
1747 op_type
= AST_BIT_OR
;
1749 op_type
= AST_BIT_OR
, invert_results
= true;
1751 op_type
= AST_BIT_XOR
;
1753 op_type
= AST_BIT_XOR
, invert_results
= true;
1757 op_type
= AST_POS
, invert_results
= true;
1758 log_assert(op_type
!= AST_NONE
);
1760 AstNode
*node
= children_list
[1];
1761 if (op_type
!= AST_POS
)
1762 for (size_t i
= 2; i
< children_list
.size(); i
++) {
1763 node
= new AstNode(op_type
, node
, children_list
[i
]);
1764 node
->location
= location
;
1767 node
= new AstNode(AST_BIT_NOT
, node
);
1771 children
.push_back(children_list
[0]);
1772 children
.back()->was_checked
= true;
1773 children
.push_back(node
);
1774 did_something
= true;
1778 // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
1779 // either a big case block that selects the correct single-bit assignment, or mask and
1780 // shift operations.
1781 if (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
)
1783 if (children
[0]->type
!= AST_IDENTIFIER
|| children
[0]->children
.size() == 0)
1784 goto skip_dynamic_range_lvalue_expansion
;
1785 if (children
[0]->children
[0]->range_valid
|| did_something
)
1786 goto skip_dynamic_range_lvalue_expansion
;
1787 if (children
[0]->id2ast
== NULL
|| children
[0]->id2ast
->type
!= AST_WIRE
)
1788 goto skip_dynamic_range_lvalue_expansion
;
1789 if (!children
[0]->id2ast
->range_valid
)
1790 goto skip_dynamic_range_lvalue_expansion
;
1792 int source_width
= children
[0]->id2ast
->range_left
- children
[0]->id2ast
->range_right
+ 1;
1793 int result_width
= 1;
1795 AstNode
*shift_expr
= NULL
;
1796 AstNode
*range
= children
[0]->children
[0];
1798 if (range
->children
.size() == 1) {
1799 shift_expr
= range
->children
[0]->clone();
1801 shift_expr
= range
->children
[1]->clone();
1802 AstNode
*left_at_zero_ast
= range
->children
[0]->clone();
1803 AstNode
*right_at_zero_ast
= range
->children
[1]->clone();
1804 while (left_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1805 while (right_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1806 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
1807 log_file_error(filename
, location
.first_line
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
1808 result_width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
1811 bool use_case_method
= false;
1813 if (children
[0]->id2ast
->attributes
.count(ID::nowrshmsk
)) {
1814 AstNode
*node
= children
[0]->id2ast
->attributes
.at(ID::nowrshmsk
);
1815 while (node
->simplify(true, false, false, stage
, -1, false, false)) { }
1816 if (node
->type
!= AST_CONSTANT
)
1817 log_file_error(filename
, location
.first_line
, "Non-constant value for `nowrshmsk' attribute on `%s'!\n", children
[0]->id2ast
->str
.c_str());
1818 if (node
->asAttrConst().as_bool())
1819 use_case_method
= true;
1822 if (use_case_method
)
1826 did_something
= true;
1827 newNode
= new AstNode(AST_CASE
, shift_expr
);
1828 for (int i
= 0; i
< source_width
; i
++) {
1829 int start_bit
= children
[0]->id2ast
->range_right
+ i
;
1830 int end_bit
= std::min(start_bit
+result_width
,source_width
) - 1;
1831 AstNode
*cond
= new AstNode(AST_COND
, mkconst_int(start_bit
, true));
1832 AstNode
*lvalue
= children
[0]->clone();
1833 lvalue
->delete_children();
1834 lvalue
->children
.push_back(new AstNode(AST_RANGE
,
1835 mkconst_int(end_bit
, true), mkconst_int(start_bit
, true)));
1836 cond
->children
.push_back(new AstNode(AST_BLOCK
, new AstNode(type
, lvalue
, children
[1]->clone())));
1837 newNode
->children
.push_back(cond
);
1842 // mask and shift operations, disabled for now
1844 AstNode
*wire_mask
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(source_width
-1, true), mkconst_int(0, true)));
1845 wire_mask
->str
= stringf("$bitselwrite$mask$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
1846 wire_mask
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
1847 wire_mask
->is_logic
= true;
1848 while (wire_mask
->simplify(true, false, false, 1, -1, false, false)) { }
1849 current_ast_mod
->children
.push_back(wire_mask
);
1851 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(source_width
-1, true), mkconst_int(0, true)));
1852 wire_data
->str
= stringf("$bitselwrite$data$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
1853 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
1854 wire_data
->is_logic
= true;
1855 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
1856 current_ast_mod
->children
.push_back(wire_data
);
1858 did_something
= true;
1859 newNode
= new AstNode(AST_BLOCK
);
1861 AstNode
*lvalue
= children
[0]->clone();
1862 lvalue
->delete_children();
1864 AstNode
*ref_mask
= new AstNode(AST_IDENTIFIER
);
1865 ref_mask
->str
= wire_mask
->str
;
1866 ref_mask
->id2ast
= wire_mask
;
1867 ref_mask
->was_checked
= true;
1869 AstNode
*ref_data
= new AstNode(AST_IDENTIFIER
);
1870 ref_data
->str
= wire_data
->str
;
1871 ref_data
->id2ast
= wire_data
;
1872 ref_data
->was_checked
= true;
1874 AstNode
*old_data
= lvalue
->clone();
1875 if (type
== AST_ASSIGN_LE
)
1876 old_data
->lookahead
= true;
1878 AstNode
*shamt
= shift_expr
;
1880 int shamt_width_hint
= 0;
1881 bool shamt_sign_hint
= true;
1882 shamt
->detectSignWidth(shamt_width_hint
, shamt_sign_hint
);
1884 int start_bit
= children
[0]->id2ast
->range_right
;
1885 bool use_shift
= shamt_sign_hint
;
1887 if (start_bit
!= 0) {
1888 shamt
= new AstNode(AST_SUB
, shamt
, mkconst_int(start_bit
, true));
1894 t
= mkconst_bits(std::vector
<RTLIL::State
>(result_width
, State::S1
), false);
1896 t
= new AstNode(AST_SHIFT
, t
, new AstNode(AST_NEG
, shamt
->clone()));
1898 t
= new AstNode(AST_SHIFT_LEFT
, t
, shamt
->clone());
1899 t
= new AstNode(AST_ASSIGN_EQ
, ref_mask
->clone(), t
);
1900 newNode
->children
.push_back(t
);
1902 t
= new AstNode(AST_BIT_AND
, mkconst_bits(std::vector
<RTLIL::State
>(result_width
, State::S1
), false), children
[1]->clone());
1904 t
= new AstNode(AST_SHIFT
, t
, new AstNode(AST_NEG
, shamt
));
1906 t
= new AstNode(AST_SHIFT_LEFT
, t
, shamt
);
1907 t
= new AstNode(AST_ASSIGN_EQ
, ref_data
->clone(), t
);
1908 newNode
->children
.push_back(t
);
1910 t
= new AstNode(AST_BIT_AND
, old_data
, new AstNode(AST_BIT_NOT
, ref_mask
));
1911 t
= new AstNode(AST_BIT_OR
, t
, ref_data
);
1912 t
= new AstNode(type
, lvalue
, t
);
1913 newNode
->children
.push_back(t
);
1918 skip_dynamic_range_lvalue_expansion
:;
1920 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && current_block
!= NULL
)
1922 std::stringstream sstr
;
1923 sstr
<< "$formal$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
1924 std::string id_check
= sstr
.str() + "_CHECK", id_en
= sstr
.str() + "_EN";
1926 AstNode
*wire_check
= new AstNode(AST_WIRE
);
1927 wire_check
->str
= id_check
;
1928 wire_check
->was_checked
= true;
1929 current_ast_mod
->children
.push_back(wire_check
);
1930 current_scope
[wire_check
->str
] = wire_check
;
1931 while (wire_check
->simplify(true, false, false, 1, -1, false, false)) { }
1933 AstNode
*wire_en
= new AstNode(AST_WIRE
);
1934 wire_en
->str
= id_en
;
1935 wire_en
->was_checked
= true;
1936 current_ast_mod
->children
.push_back(wire_en
);
1937 if (current_always_clocked
) {
1938 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)))));
1939 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->str
= id_en
;
1940 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->was_checked
= true;
1942 current_scope
[wire_en
->str
] = wire_en
;
1943 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
1945 AstNode
*check_defval
;
1946 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
1947 check_defval
= new AstNode(AST_REDUCE_BOOL
, children
[0]->clone());
1949 std::vector
<RTLIL::State
> x_bit
;
1950 x_bit
.push_back(RTLIL::State::Sx
);
1951 check_defval
= mkconst_bits(x_bit
, false);
1954 AstNode
*assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), check_defval
);
1955 assign_check
->children
[0]->str
= id_check
;
1956 assign_check
->children
[0]->was_checked
= true;
1958 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, 1));
1959 assign_en
->children
[0]->str
= id_en
;
1960 assign_en
->children
[0]->was_checked
= true;
1962 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
1963 default_signals
->children
.push_back(assign_check
);
1964 default_signals
->children
.push_back(assign_en
);
1965 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
1967 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
1968 assign_check
= nullptr;
1970 assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_REDUCE_BOOL
, children
[0]->clone()));
1971 assign_check
->children
[0]->str
= id_check
;
1972 assign_check
->children
[0]->was_checked
= true;
1975 if (current_always
== nullptr || current_always
->type
!= AST_INITIAL
) {
1976 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(1, false, 1));
1978 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_FCALL
));
1979 assign_en
->children
[1]->str
= "\\$initstate";
1981 assign_en
->children
[0]->str
= id_en
;
1982 assign_en
->children
[0]->was_checked
= true;
1984 newNode
= new AstNode(AST_BLOCK
);
1985 if (assign_check
!= nullptr)
1986 newNode
->children
.push_back(assign_check
);
1987 newNode
->children
.push_back(assign_en
);
1989 AstNode
*assertnode
= new AstNode(type
);
1990 assertnode
->location
= location
;
1991 assertnode
->str
= str
;
1992 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1993 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1994 assertnode
->children
[0]->str
= id_check
;
1995 assertnode
->children
[1]->str
= id_en
;
1996 assertnode
->attributes
.swap(attributes
);
1997 current_ast_mod
->children
.push_back(assertnode
);
2002 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && children
.size() == 1)
2004 children
.push_back(mkconst_int(1, false, 1));
2005 did_something
= true;
2008 // found right-hand side identifier for memory -> replace with memory read port
2009 if (stage
> 1 && type
== AST_IDENTIFIER
&& id2ast
!= NULL
&& id2ast
->type
== AST_MEMORY
&& !in_lvalue
&&
2010 children
.size() == 1 && children
[0]->type
== AST_RANGE
&& children
[0]->children
.size() == 1) {
2011 newNode
= new AstNode(AST_MEMRD
, children
[0]->children
[0]->clone());
2013 newNode
->id2ast
= id2ast
;
2017 // assignment with nontrivial member in left-hand concat expression -> split assignment
2018 if ((type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_CONCAT
&& width_hint
> 0)
2020 bool found_nontrivial_member
= false;
2022 for (auto child
: children
[0]->children
) {
2023 if (child
->type
== AST_IDENTIFIER
&& child
->id2ast
!= NULL
&& child
->id2ast
->type
== AST_MEMORY
)
2024 found_nontrivial_member
= true;
2027 if (found_nontrivial_member
)
2029 newNode
= new AstNode(AST_BLOCK
);
2031 AstNode
*wire_tmp
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
2032 wire_tmp
->str
= stringf("$splitcmplxassign$%s:%d$%d", filename
.c_str(), location
.first_line
, autoidx
++);
2033 current_ast_mod
->children
.push_back(wire_tmp
);
2034 current_scope
[wire_tmp
->str
] = wire_tmp
;
2035 wire_tmp
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
2036 while (wire_tmp
->simplify(true, false, false, 1, -1, false, false)) { }
2037 wire_tmp
->is_logic
= true;
2039 AstNode
*wire_tmp_id
= new AstNode(AST_IDENTIFIER
);
2040 wire_tmp_id
->str
= wire_tmp
->str
;
2042 newNode
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, wire_tmp_id
, children
[1]->clone()));
2043 newNode
->children
.back()->was_checked
= true;
2046 for (auto child
: children
[0]->children
)
2048 int child_width_hint
= -1;
2049 bool child_sign_hint
= true;
2050 child
->detectSignWidth(child_width_hint
, child_sign_hint
);
2052 AstNode
*rhs
= wire_tmp_id
->clone();
2053 rhs
->children
.push_back(new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+child_width_hint
-1, true), AstNode::mkconst_int(cursor
, true)));
2054 newNode
->children
.push_back(new AstNode(type
, child
->clone(), rhs
));
2056 cursor
+= child_width_hint
;
2063 // assignment with memory in left-hand side expression -> replace with memory write port
2064 if (stage
> 1 && (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_IDENTIFIER
&&
2065 children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
&& children
[0]->id2ast
->children
.size() >= 2 &&
2066 children
[0]->id2ast
->children
[0]->range_valid
&& children
[0]->id2ast
->children
[1]->range_valid
&&
2067 (children
[0]->children
.size() == 1 || children
[0]->children
.size() == 2) && children
[0]->children
[0]->type
== AST_RANGE
)
2069 std::stringstream sstr
;
2070 sstr
<< "$memwr$" << children
[0]->str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
2071 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA", id_en
= sstr
.str() + "_EN";
2073 int mem_width
, mem_size
, addr_bits
;
2074 bool mem_signed
= children
[0]->id2ast
->is_signed
;
2075 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
2077 newNode
= new AstNode(AST_BLOCK
);
2078 AstNode
*defNode
= new AstNode(AST_BLOCK
);
2080 int data_range_left
= children
[0]->id2ast
->children
[0]->range_left
;
2081 int data_range_right
= children
[0]->id2ast
->children
[0]->range_right
;
2082 int mem_data_range_offset
= std::min(data_range_left
, data_range_right
);
2084 int addr_width_hint
= -1;
2085 bool addr_sign_hint
= true;
2086 children
[0]->children
[0]->children
[0]->detectSignWidthWorker(addr_width_hint
, addr_sign_hint
);
2087 addr_bits
= std::max(addr_bits
, addr_width_hint
);
2089 std::vector
<RTLIL::State
> x_bits_addr
, x_bits_data
, set_bits_en
;
2090 for (int i
= 0; i
< addr_bits
; i
++)
2091 x_bits_addr
.push_back(RTLIL::State::Sx
);
2092 for (int i
= 0; i
< mem_width
; i
++)
2093 x_bits_data
.push_back(RTLIL::State::Sx
);
2094 for (int i
= 0; i
< mem_width
; i
++)
2095 set_bits_en
.push_back(RTLIL::State::S1
);
2097 AstNode
*node_addr
= nullptr;
2098 if (children
[0]->children
[0]->children
[0]->isConst()) {
2099 node_addr
= children
[0]->children
[0]->children
[0]->clone();
2101 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
2102 wire_addr
->str
= id_addr
;
2103 wire_addr
->was_checked
= true;
2104 current_ast_mod
->children
.push_back(wire_addr
);
2105 current_scope
[wire_addr
->str
] = wire_addr
;
2106 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
2108 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_addr
, false));
2109 assign_addr
->children
[0]->str
= id_addr
;
2110 assign_addr
->children
[0]->was_checked
= true;
2111 defNode
->children
.push_back(assign_addr
);
2113 assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
2114 assign_addr
->children
[0]->str
= id_addr
;
2115 assign_addr
->children
[0]->was_checked
= true;
2116 newNode
->children
.push_back(assign_addr
);
2118 node_addr
= new AstNode(AST_IDENTIFIER
);
2119 node_addr
->str
= id_addr
;
2122 AstNode
*node_data
= nullptr;
2123 if (children
[0]->children
.size() == 1 && children
[1]->isConst()) {
2124 node_data
= children
[1]->clone();
2126 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
2127 wire_data
->str
= id_data
;
2128 wire_data
->was_checked
= true;
2129 wire_data
->is_signed
= mem_signed
;
2130 current_ast_mod
->children
.push_back(wire_data
);
2131 current_scope
[wire_data
->str
] = wire_data
;
2132 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
2134 AstNode
*assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_data
, false));
2135 assign_data
->children
[0]->str
= id_data
;
2136 assign_data
->children
[0]->was_checked
= true;
2137 defNode
->children
.push_back(assign_data
);
2139 node_data
= new AstNode(AST_IDENTIFIER
);
2140 node_data
->str
= id_data
;
2143 AstNode
*node_en
= nullptr;
2144 if (current_always
->type
== AST_INITIAL
) {
2145 node_en
= AstNode::mkconst_int(1, false);
2147 AstNode
*wire_en
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
2148 wire_en
->str
= id_en
;
2149 wire_en
->was_checked
= true;
2150 current_ast_mod
->children
.push_back(wire_en
);
2151 current_scope
[wire_en
->str
] = wire_en
;
2152 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
2154 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, mem_width
));
2155 assign_en
->children
[0]->str
= id_en
;
2156 assign_en
->children
[0]->was_checked
= true;
2157 defNode
->children
.push_back(assign_en
);
2159 node_en
= new AstNode(AST_IDENTIFIER
);
2160 node_en
->str
= id_en
;
2163 if (!defNode
->children
.empty())
2164 current_top_block
->children
.insert(current_top_block
->children
.begin(), defNode
);
2168 AstNode
*assign_data
= nullptr;
2169 AstNode
*assign_en
= nullptr;
2170 if (children
[0]->children
.size() == 2)
2172 if (children
[0]->children
[1]->range_valid
)
2174 int offset
= children
[0]->children
[1]->range_right
;
2175 int width
= children
[0]->children
[1]->range_left
- offset
+ 1;
2176 offset
-= mem_data_range_offset
;
2178 std::vector
<RTLIL::State
> padding_x(offset
, RTLIL::State::Sx
);
2180 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
2181 new AstNode(AST_CONCAT
, mkconst_bits(padding_x
, false), children
[1]->clone()));
2182 assign_data
->children
[0]->str
= id_data
;
2183 assign_data
->children
[0]->was_checked
= true;
2185 if (current_always
->type
!= AST_INITIAL
) {
2186 for (int i
= 0; i
< mem_width
; i
++)
2187 set_bits_en
[i
] = offset
<= i
&& i
< offset
+width
? RTLIL::State::S1
: RTLIL::State::S0
;
2188 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
2189 assign_en
->children
[0]->str
= id_en
;
2190 assign_en
->children
[0]->was_checked
= true;
2195 AstNode
*the_range
= children
[0]->children
[1];
2196 AstNode
*left_at_zero_ast
= the_range
->children
[0]->clone();
2197 AstNode
*right_at_zero_ast
= the_range
->children
.size() >= 2 ? the_range
->children
[1]->clone() : left_at_zero_ast
->clone();
2198 AstNode
*offset_ast
= right_at_zero_ast
->clone();
2200 if (mem_data_range_offset
)
2201 offset_ast
= new AstNode(AST_SUB
, offset_ast
, mkconst_int(mem_data_range_offset
, true));
2203 while (left_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
2204 while (right_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
2205 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
2206 log_file_error(filename
, location
.first_line
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
2207 int width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
2209 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
2210 new AstNode(AST_SHIFT_LEFT
, children
[1]->clone(), offset_ast
->clone()));
2211 assign_data
->children
[0]->str
= id_data
;
2212 assign_data
->children
[0]->was_checked
= true;
2214 if (current_always
->type
!= AST_INITIAL
) {
2215 for (int i
= 0; i
< mem_width
; i
++)
2216 set_bits_en
[i
] = i
< width
? RTLIL::State::S1
: RTLIL::State::S0
;
2217 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
2218 new AstNode(AST_SHIFT_LEFT
, mkconst_bits(set_bits_en
, false), offset_ast
->clone()));
2219 assign_en
->children
[0]->str
= id_en
;
2220 assign_en
->children
[0]->was_checked
= true;
2223 delete left_at_zero_ast
;
2224 delete right_at_zero_ast
;
2230 if (!(children
[0]->children
.size() == 1 && children
[1]->isConst())) {
2231 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[1]->clone());
2232 assign_data
->children
[0]->str
= id_data
;
2233 assign_data
->children
[0]->was_checked
= true;
2236 if (current_always
->type
!= AST_INITIAL
) {
2237 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
2238 assign_en
->children
[0]->str
= id_en
;
2239 assign_en
->children
[0]->was_checked
= true;
2243 newNode
->children
.push_back(assign_data
);
2245 newNode
->children
.push_back(assign_en
);
2247 AstNode
*wrnode
= new AstNode(current_always
->type
== AST_INITIAL
? AST_MEMINIT
: AST_MEMWR
, node_addr
, node_data
, node_en
);
2248 wrnode
->str
= children
[0]->str
;
2249 wrnode
->id2ast
= children
[0]->id2ast
;
2250 current_ast_mod
->children
.push_back(wrnode
);
2252 if (newNode
->children
.empty()) {
2254 newNode
= new AstNode();
2259 // replace function and task calls with the code from the function or task
2260 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && !str
.empty())
2262 if (type
== AST_FCALL
)
2264 if (str
== "\\$initstate")
2266 int myidx
= autoidx
++;
2268 AstNode
*wire
= new AstNode(AST_WIRE
);
2269 wire
->str
= stringf("$initstate$%d_wire", myidx
);
2270 current_ast_mod
->children
.push_back(wire
);
2271 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2273 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
), new AstNode(AST_ARGUMENT
, new AstNode(AST_IDENTIFIER
)));
2274 cell
->str
= stringf("$initstate$%d", myidx
);
2275 cell
->children
[0]->str
= "$initstate";
2276 cell
->children
[1]->str
= "\\Y";
2277 cell
->children
[1]->children
[0]->str
= wire
->str
;
2278 cell
->children
[1]->children
[0]->id2ast
= wire
;
2279 current_ast_mod
->children
.push_back(cell
);
2280 while (cell
->simplify(true, false, false, 1, -1, false, false)) { }
2282 newNode
= new AstNode(AST_IDENTIFIER
);
2283 newNode
->str
= wire
->str
;
2284 newNode
->id2ast
= wire
;
2288 if (str
== "\\$past")
2291 goto replace_fcall_later
;
2295 if (GetSize(children
) != 1 && GetSize(children
) != 2)
2296 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1 or 2.\n",
2297 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2299 if (!current_always_clocked
)
2300 log_file_error(filename
, location
.first_line
, "System function %s is only allowed in clocked blocks.\n",
2301 RTLIL::unescape_id(str
).c_str());
2303 if (GetSize(children
) == 2)
2305 AstNode
*buf
= children
[1]->clone();
2306 while (buf
->simplify(true, false, false, stage
, -1, false, false)) { }
2307 if (buf
->type
!= AST_CONSTANT
)
2308 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
2310 num_steps
= buf
->asInt(true);
2314 AstNode
*block
= nullptr;
2316 for (auto child
: current_always
->children
)
2317 if (child
->type
== AST_BLOCK
)
2320 log_assert(block
!= nullptr);
2322 if (num_steps
== 0) {
2323 newNode
= children
[0]->clone();
2327 int myidx
= autoidx
++;
2328 AstNode
*outreg
= nullptr;
2330 for (int i
= 0; i
< num_steps
; i
++)
2332 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
2333 mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
2335 reg
->str
= stringf("$past$%s:%d$%d$%d", filename
.c_str(), location
.first_line
, myidx
, i
);
2338 current_ast_mod
->children
.push_back(reg
);
2340 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
2342 AstNode
*regid
= new AstNode(AST_IDENTIFIER
);
2343 regid
->str
= reg
->str
;
2344 regid
->id2ast
= reg
;
2345 regid
->was_checked
= true;
2347 AstNode
*rhs
= nullptr;
2349 if (outreg
== nullptr) {
2350 rhs
= children
.at(0)->clone();
2352 rhs
= new AstNode(AST_IDENTIFIER
);
2353 rhs
->str
= outreg
->str
;
2354 rhs
->id2ast
= outreg
;
2357 block
->children
.push_back(new AstNode(AST_ASSIGN_LE
, regid
, rhs
));
2361 newNode
= new AstNode(AST_IDENTIFIER
);
2362 newNode
->str
= outreg
->str
;
2363 newNode
->id2ast
= outreg
;
2367 if (str
== "\\$stable" || str
== "\\$rose" || str
== "\\$fell" || str
== "\\$changed")
2369 if (GetSize(children
) != 1)
2370 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2371 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2373 if (!current_always_clocked
)
2374 log_file_error(filename
, location
.first_line
, "System function %s is only allowed in clocked blocks.\n",
2375 RTLIL::unescape_id(str
).c_str());
2377 AstNode
*present
= children
.at(0)->clone();
2378 AstNode
*past
= clone();
2379 past
->str
= "\\$past";
2381 if (str
== "\\$stable")
2382 newNode
= new AstNode(AST_EQ
, past
, present
);
2384 else if (str
== "\\$changed")
2385 newNode
= new AstNode(AST_NE
, past
, present
);
2387 else if (str
== "\\$rose")
2388 newNode
= new AstNode(AST_LOGIC_AND
,
2389 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false))),
2390 new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false)));
2392 else if (str
== "\\$fell")
2393 newNode
= new AstNode(AST_LOGIC_AND
,
2394 new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false)),
2395 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false))));
2403 // $anyconst and $anyseq are mapped in AstNode::genRTLIL()
2404 if (str
== "\\$anyconst" || str
== "\\$anyseq" || str
== "\\$allconst" || str
== "\\$allseq") {
2405 recursion_counter
--;
2409 if (str
== "\\$clog2")
2411 if (children
.size() != 1)
2412 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2413 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2415 AstNode
*buf
= children
[0]->clone();
2416 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2417 if (buf
->type
!= AST_CONSTANT
)
2418 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
2420 RTLIL::Const arg_value
= buf
->bitsAsConst();
2421 if (arg_value
.as_bool())
2422 arg_value
= const_sub(arg_value
, 1, false, false, GetSize(arg_value
));
2425 uint32_t result
= 0;
2426 for (size_t i
= 0; i
< arg_value
.bits
.size(); i
++)
2427 if (arg_value
.bits
.at(i
) == RTLIL::State::S1
)
2430 newNode
= mkconst_int(result
, true);
2434 if (str
== "\\$size" || str
== "\\$bits")
2436 if (str
== "\\$bits" && children
.size() != 1)
2437 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2438 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2440 if (str
== "\\$size" && children
.size() != 1 && children
.size() != 2)
2441 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1 or 2.\n",
2442 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2445 if (str
== "\\$size" && children
.size() == 2) {
2446 AstNode
*buf
= children
[1]->clone();
2447 // Evaluate constant expression
2448 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2449 dim
= buf
->asInt(false);
2452 AstNode
*buf
= children
[0]->clone();
2454 AstNode
*id_ast
= NULL
;
2457 //while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2458 buf
->detectSignWidth(width_hint
, sign_hint
);
2460 if (buf
->type
== AST_IDENTIFIER
) {
2461 id_ast
= buf
->id2ast
;
2462 if (id_ast
== NULL
&& current_scope
.count(buf
->str
))
2463 id_ast
= current_scope
.at(buf
->str
);
2465 log_file_error(filename
, location
.first_line
, "Failed to resolve identifier %s for width detection!\n", buf
->str
.c_str());
2466 if (id_ast
->type
== AST_MEMORY
) {
2467 // We got here only if the argument is a memory
2468 // Otherwise $size() and $bits() return the expression width
2469 AstNode
*mem_range
= id_ast
->children
[1];
2470 if (str
== "\\$bits") {
2471 if (mem_range
->type
== AST_RANGE
) {
2472 if (!mem_range
->range_valid
)
2473 log_file_error(filename
, location
.first_line
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2474 mem_depth
= mem_range
->range_left
- mem_range
->range_right
+ 1;
2476 log_file_error(filename
, location
.first_line
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2479 if (mem_range
->type
== AST_RANGE
) {
2480 if (!mem_range
->range_valid
)
2481 log_file_error(filename
, location
.first_line
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2483 if (id_ast
->multirange_dimensions
.empty())
2486 dims
= GetSize(id_ast
->multirange_dimensions
)/2;
2488 width_hint
= (dims
> 1) ? id_ast
->multirange_dimensions
[1] : (mem_range
->range_left
- mem_range
->range_right
+ 1);
2489 else if (dim
<= dims
) {
2490 width_hint
= id_ast
->multirange_dimensions
[2*dim
-1];
2491 } else if ((dim
> dims
+1) || (dim
< 0))
2492 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);
2494 log_file_error(filename
, location
.first_line
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2500 newNode
= mkconst_int(width_hint
* mem_depth
, false);
2504 if (str
== "\\$ln" || str
== "\\$log10" || str
== "\\$exp" || str
== "\\$sqrt" || str
== "\\$pow" ||
2505 str
== "\\$floor" || str
== "\\$ceil" || str
== "\\$sin" || str
== "\\$cos" || str
== "\\$tan" ||
2506 str
== "\\$asin" || str
== "\\$acos" || str
== "\\$atan" || str
== "\\$atan2" || str
== "\\$hypot" ||
2507 str
== "\\$sinh" || str
== "\\$cosh" || str
== "\\$tanh" || str
== "\\$asinh" || str
== "\\$acosh" || str
== "\\$atanh" ||
2508 str
== "\\$rtoi" || str
== "\\$itor")
2510 bool func_with_two_arguments
= str
== "\\$pow" || str
== "\\$atan2" || str
== "\\$hypot";
2511 double x
= 0, y
= 0;
2513 if (func_with_two_arguments
) {
2514 if (children
.size() != 2)
2515 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 2.\n",
2516 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2518 if (children
.size() != 1)
2519 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 1.\n",
2520 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2523 if (children
.size() >= 1) {
2524 while (children
[0]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2525 if (!children
[0]->isConst())
2526 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant argument.\n",
2527 RTLIL::unescape_id(str
).c_str());
2528 int child_width_hint
= width_hint
;
2529 bool child_sign_hint
= sign_hint
;
2530 children
[0]->detectSignWidth(child_width_hint
, child_sign_hint
);
2531 x
= children
[0]->asReal(child_sign_hint
);
2534 if (children
.size() >= 2) {
2535 while (children
[1]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2536 if (!children
[1]->isConst())
2537 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant argument.\n",
2538 RTLIL::unescape_id(str
).c_str());
2539 int child_width_hint
= width_hint
;
2540 bool child_sign_hint
= sign_hint
;
2541 children
[1]->detectSignWidth(child_width_hint
, child_sign_hint
);
2542 y
= children
[1]->asReal(child_sign_hint
);
2545 if (str
== "\\$rtoi") {
2546 newNode
= AstNode::mkconst_int(x
, true);
2548 newNode
= new AstNode(AST_REALVALUE
);
2549 if (str
== "\\$ln") newNode
->realvalue
= ::log(x
);
2550 else if (str
== "\\$log10") newNode
->realvalue
= ::log10(x
);
2551 else if (str
== "\\$exp") newNode
->realvalue
= ::exp(x
);
2552 else if (str
== "\\$sqrt") newNode
->realvalue
= ::sqrt(x
);
2553 else if (str
== "\\$pow") newNode
->realvalue
= ::pow(x
, y
);
2554 else if (str
== "\\$floor") newNode
->realvalue
= ::floor(x
);
2555 else if (str
== "\\$ceil") newNode
->realvalue
= ::ceil(x
);
2556 else if (str
== "\\$sin") newNode
->realvalue
= ::sin(x
);
2557 else if (str
== "\\$cos") newNode
->realvalue
= ::cos(x
);
2558 else if (str
== "\\$tan") newNode
->realvalue
= ::tan(x
);
2559 else if (str
== "\\$asin") newNode
->realvalue
= ::asin(x
);
2560 else if (str
== "\\$acos") newNode
->realvalue
= ::acos(x
);
2561 else if (str
== "\\$atan") newNode
->realvalue
= ::atan(x
);
2562 else if (str
== "\\$atan2") newNode
->realvalue
= ::atan2(x
, y
);
2563 else if (str
== "\\$hypot") newNode
->realvalue
= ::hypot(x
, y
);
2564 else if (str
== "\\$sinh") newNode
->realvalue
= ::sinh(x
);
2565 else if (str
== "\\$cosh") newNode
->realvalue
= ::cosh(x
);
2566 else if (str
== "\\$tanh") newNode
->realvalue
= ::tanh(x
);
2567 else if (str
== "\\$asinh") newNode
->realvalue
= ::asinh(x
);
2568 else if (str
== "\\$acosh") newNode
->realvalue
= ::acosh(x
);
2569 else if (str
== "\\$atanh") newNode
->realvalue
= ::atanh(x
);
2570 else if (str
== "\\$itor") newNode
->realvalue
= x
;
2576 if (str
== "\\$sformatf") {
2577 AstNode
*node_string
= children
[0];
2578 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2579 if (node_string
->type
!= AST_CONSTANT
)
2580 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
2581 std::string sformat
= node_string
->bitsAsConst().decode_string();
2582 std::string sout
= process_format_str(sformat
, 1, stage
, width_hint
, sign_hint
);
2583 newNode
= AstNode::mkconst_str(sout
);
2587 if (current_scope
.count(str
) != 0 && current_scope
[str
]->type
== AST_DPI_FUNCTION
)
2589 AstNode
*dpi_decl
= current_scope
[str
];
2591 std::string rtype
, fname
;
2592 std::vector
<std::string
> argtypes
;
2593 std::vector
<AstNode
*> args
;
2595 rtype
= RTLIL::unescape_id(dpi_decl
->children
.at(0)->str
);
2596 fname
= RTLIL::unescape_id(dpi_decl
->children
.at(1)->str
);
2598 for (int i
= 2; i
< GetSize(dpi_decl
->children
); i
++)
2600 if (i
-2 >= GetSize(children
))
2601 log_file_error(filename
, location
.first_line
, "Insufficient number of arguments in DPI function call.\n");
2603 argtypes
.push_back(RTLIL::unescape_id(dpi_decl
->children
.at(i
)->str
));
2604 args
.push_back(children
.at(i
-2)->clone());
2605 while (args
.back()->simplify(true, false, false, stage
, -1, false, true)) { }
2607 if (args
.back()->type
!= AST_CONSTANT
&& args
.back()->type
!= AST_REALVALUE
)
2608 log_file_error(filename
, location
.first_line
, "Failed to evaluate DPI function with non-constant argument.\n");
2611 newNode
= dpi_call(rtype
, fname
, argtypes
, args
);
2613 for (auto arg
: args
)
2619 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_FUNCTION
)
2620 log_file_error(filename
, location
.first_line
, "Can't resolve function name `%s'.\n", str
.c_str());
2623 if (type
== AST_TCALL
)
2625 if (str
== "$finish" || str
== "$stop")
2627 if (!current_always
|| current_always
->type
!= AST_INITIAL
)
2628 log_file_error(filename
, location
.first_line
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
2630 log_file_error(filename
, location
.first_line
, "System task `%s' executed.\n", str
.c_str());
2633 if (str
== "\\$readmemh" || str
== "\\$readmemb")
2635 if (GetSize(children
) < 2 || GetSize(children
) > 4)
2636 log_file_error(filename
, location
.first_line
, "System function %s got %d arguments, expected 2-4.\n",
2637 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2639 AstNode
*node_filename
= children
[0]->clone();
2640 while (node_filename
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2641 if (node_filename
->type
!= AST_CONSTANT
)
2642 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
2644 AstNode
*node_memory
= children
[1]->clone();
2645 while (node_memory
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2646 if (node_memory
->type
!= AST_IDENTIFIER
|| node_memory
->id2ast
== nullptr || node_memory
->id2ast
->type
!= AST_MEMORY
)
2647 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str
.c_str());
2649 int start_addr
= -1, finish_addr
= -1;
2651 if (GetSize(children
) > 2) {
2652 AstNode
*node_addr
= children
[2]->clone();
2653 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2654 if (node_addr
->type
!= AST_CONSTANT
)
2655 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str
.c_str());
2656 start_addr
= int(node_addr
->asInt(false));
2659 if (GetSize(children
) > 3) {
2660 AstNode
*node_addr
= children
[3]->clone();
2661 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2662 if (node_addr
->type
!= AST_CONSTANT
)
2663 log_file_error(filename
, location
.first_line
, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str
.c_str());
2664 finish_addr
= int(node_addr
->asInt(false));
2667 bool unconditional_init
= false;
2668 if (current_always
->type
== AST_INITIAL
) {
2669 pool
<AstNode
*> queue
;
2670 log_assert(current_always
->children
[0]->type
== AST_BLOCK
);
2671 queue
.insert(current_always
->children
[0]);
2672 while (!unconditional_init
&& !queue
.empty()) {
2673 pool
<AstNode
*> next_queue
;
2674 for (auto n
: queue
)
2675 for (auto c
: n
->children
) {
2677 unconditional_init
= true;
2678 next_queue
.insert(c
);
2680 next_queue
.swap(queue
);
2684 newNode
= readmem(str
== "\\$readmemh", node_filename
->bitsAsConst().decode_string(), node_memory
->id2ast
, start_addr
, finish_addr
, unconditional_init
);
2685 delete node_filename
;
2690 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_TASK
)
2691 log_file_error(filename
, location
.first_line
, "Can't resolve task name `%s'.\n", str
.c_str());
2694 AstNode
*decl
= current_scope
[str
];
2696 std::stringstream sstr
;
2697 sstr
<< "$func$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++) << "$";
2698 std::string prefix
= sstr
.str();
2700 bool recommend_const_eval
= false;
2701 bool require_const_eval
= in_param
? false : has_const_only_constructs(recommend_const_eval
);
2702 if ((in_param
|| recommend_const_eval
|| require_const_eval
) && !decl
->attributes
.count(ID::via_celltype
))
2704 bool all_args_const
= true;
2705 for (auto child
: children
) {
2706 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
2707 if (child
->type
!= AST_CONSTANT
)
2708 all_args_const
= false;
2711 if (all_args_const
) {
2712 AstNode
*func_workspace
= current_scope
[str
]->clone();
2713 newNode
= func_workspace
->eval_const_function(this);
2714 delete func_workspace
;
2719 log_file_error(filename
, location
.first_line
, "Non-constant function call in constant expression.\n");
2720 if (require_const_eval
)
2721 log_file_error(filename
, location
.first_line
, "Function %s can only be called with constant arguments.\n", str
.c_str());
2724 size_t arg_count
= 0;
2725 std::map
<std::string
, std::string
> replace_rules
;
2726 vector
<AstNode
*> added_mod_children
;
2727 dict
<std::string
, AstNode
*> wire_cache
;
2728 vector
<AstNode
*> new_stmts
;
2729 vector
<AstNode
*> output_assignments
;
2731 if (current_block
== NULL
)
2733 log_assert(type
== AST_FCALL
);
2735 AstNode
*wire
= NULL
;
2736 for (auto child
: decl
->children
)
2737 if (child
->type
== AST_WIRE
&& child
->str
== str
)
2738 wire
= child
->clone();
2739 log_assert(wire
!= NULL
);
2741 wire
->str
= prefix
+ str
;
2743 wire
->is_input
= false;
2744 wire
->is_output
= false;
2746 current_ast_mod
->children
.push_back(wire
);
2747 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2749 AstNode
*lvalue
= new AstNode(AST_IDENTIFIER
);
2750 lvalue
->str
= wire
->str
;
2752 AstNode
*always
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
,
2753 new AstNode(AST_ASSIGN_EQ
, lvalue
, clone())));
2754 always
->children
[0]->children
[0]->was_checked
= true;
2756 current_ast_mod
->children
.push_back(always
);
2758 goto replace_fcall_with_id
;
2761 if (decl
->attributes
.count(ID::via_celltype
))
2763 std::string celltype
= decl
->attributes
.at(ID::via_celltype
)->asAttrConst().decode_string();
2764 std::string outport
= str
;
2766 if (celltype
.find(' ') != std::string::npos
) {
2767 int pos
= celltype
.find(' ');
2768 outport
= RTLIL::escape_id(celltype
.substr(pos
+1));
2769 celltype
= RTLIL::escape_id(celltype
.substr(0, pos
));
2771 celltype
= RTLIL::escape_id(celltype
);
2773 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
));
2774 cell
->str
= prefix
.substr(0, GetSize(prefix
)-1);
2775 cell
->children
[0]->str
= celltype
;
2777 for (auto attr
: decl
->attributes
)
2778 if (attr
.first
.str().rfind("\\via_celltype_defparam_", 0) == 0)
2780 AstNode
*cell_arg
= new AstNode(AST_PARASET
, attr
.second
->clone());
2781 cell_arg
->str
= RTLIL::escape_id(attr
.first
.substr(strlen("\\via_celltype_defparam_")));
2782 cell
->children
.push_back(cell_arg
);
2785 for (auto child
: decl
->children
)
2786 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
|| (type
== AST_FCALL
&& child
->str
== str
)))
2788 AstNode
*wire
= child
->clone();
2789 wire
->str
= prefix
+ wire
->str
;
2791 wire
->is_input
= false;
2792 wire
->is_output
= false;
2793 current_ast_mod
->children
.push_back(wire
);
2794 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2796 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
2797 wire_id
->str
= wire
->str
;
2799 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
2801 AstNode
*arg
= children
[arg_count
++]->clone();
2802 AstNode
*assign
= child
->is_input
?
2803 new AstNode(AST_ASSIGN_EQ
, wire_id
->clone(), arg
) :
2804 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
->clone());
2805 assign
->children
[0]->was_checked
= true;
2807 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
2808 if (*it
!= current_block_child
)
2810 current_block
->children
.insert(it
, assign
);
2815 AstNode
*cell_arg
= new AstNode(AST_ARGUMENT
, wire_id
);
2816 cell_arg
->str
= child
->str
== str
? outport
: child
->str
;
2817 cell
->children
.push_back(cell_arg
);
2820 current_ast_mod
->children
.push_back(cell
);
2821 goto replace_fcall_with_id
;
2824 for (auto child
: decl
->children
)
2825 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
|| child
->type
== AST_ENUM_ITEM
)
2827 AstNode
*wire
= nullptr;
2829 if (wire_cache
.count(child
->str
))
2831 wire
= wire_cache
.at(child
->str
);
2832 if (wire
->children
.empty()) {
2833 for (auto c
: child
->children
)
2834 wire
->children
.push_back(c
->clone());
2835 } else if (!child
->children
.empty()) {
2836 while (child
->simplify(true, false, false, stage
, -1, false, false)) { }
2837 if (GetSize(child
->children
) == GetSize(wire
->children
)) {
2838 for (int i
= 0; i
< GetSize(child
->children
); i
++)
2839 if (*child
->children
.at(i
) != *wire
->children
.at(i
))
2840 goto tcall_incompatible_wires
;
2842 tcall_incompatible_wires
:
2843 log_file_error(filename
, location
.first_line
, "Incompatible re-declaration of wire %s.\n", child
->str
.c_str());
2849 wire
= child
->clone();
2850 wire
->str
= prefix
+ wire
->str
;
2852 wire
->is_input
= false;
2853 wire
->is_output
= false;
2854 wire
->is_reg
= true;
2855 wire
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
2856 if (child
->type
== AST_ENUM_ITEM
)
2857 wire
->attributes
[ID::enum_base_type
] = child
->attributes
[ID::enum_base_type
];
2859 wire_cache
[child
->str
] = wire
;
2861 current_ast_mod
->children
.push_back(wire
);
2862 added_mod_children
.push_back(wire
);
2865 if (child
->type
== AST_WIRE
)
2866 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2868 replace_rules
[child
->str
] = wire
->str
;
2869 current_scope
[wire
->str
] = wire
;
2871 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
2873 AstNode
*arg
= children
[arg_count
++]->clone();
2874 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
2875 wire_id
->str
= wire
->str
;
2876 AstNode
*assign
= child
->is_input
?
2877 new AstNode(AST_ASSIGN_EQ
, wire_id
, arg
) :
2878 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
);
2879 assign
->children
[0]->was_checked
= true;
2880 if (child
->is_input
)
2881 new_stmts
.push_back(assign
);
2883 output_assignments
.push_back(assign
);
2887 for (auto child
: added_mod_children
) {
2888 child
->replace_ids(prefix
, replace_rules
);
2889 while (child
->simplify(true, false, false, 1, -1, false, false)) { }
2892 for (auto child
: decl
->children
)
2893 if (child
->type
!= AST_WIRE
&& child
->type
!= AST_MEMORY
&& child
->type
!= AST_PARAMETER
&& child
->type
!= AST_LOCALPARAM
)
2895 AstNode
*stmt
= child
->clone();
2896 stmt
->replace_ids(prefix
, replace_rules
);
2897 new_stmts
.push_back(stmt
);
2900 new_stmts
.insert(new_stmts
.end(), output_assignments
.begin(), output_assignments
.end());
2902 for (auto it
= current_block
->children
.begin(); ; it
++) {
2903 log_assert(it
!= current_block
->children
.end());
2904 if (*it
== current_block_child
) {
2905 current_block
->children
.insert(it
, new_stmts
.begin(), new_stmts
.end());
2910 replace_fcall_with_id
:
2911 if (type
== AST_FCALL
) {
2913 type
= AST_IDENTIFIER
;
2916 if (type
== AST_TCALL
)
2918 did_something
= true;
2921 replace_fcall_later
:;
2923 // perform const folding when activated
2927 std::vector
<RTLIL::State
> tmp_bits
;
2928 RTLIL::Const (*const_func
)(const RTLIL::Const
&, const RTLIL::Const
&, bool, bool, int);
2929 RTLIL::Const dummy_arg
;
2933 case AST_IDENTIFIER
:
2934 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
)) {
2935 if (current_scope
[str
]->children
[0]->type
== AST_CONSTANT
) {
2936 if (children
.size() != 0 && children
[0]->type
== AST_RANGE
&& children
[0]->range_valid
) {
2937 std::vector
<RTLIL::State
> data
;
2938 bool param_upto
= current_scope
[str
]->range_valid
&& current_scope
[str
]->range_swapped
;
2939 int param_offset
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_right
: 0;
2940 int param_width
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_left
- current_scope
[str
]->range_right
+ 1 :
2941 GetSize(current_scope
[str
]->children
[0]->bits
);
2942 int tmp_range_left
= children
[0]->range_left
, tmp_range_right
= children
[0]->range_right
;
2944 tmp_range_left
= (param_width
+ 2*param_offset
) - children
[0]->range_right
- 1;
2945 tmp_range_right
= (param_width
+ 2*param_offset
) - children
[0]->range_left
- 1;
2947 for (int i
= tmp_range_right
; i
<= tmp_range_left
; i
++) {
2948 int index
= i
- param_offset
;
2949 if (0 <= index
&& index
< param_width
)
2950 data
.push_back(current_scope
[str
]->children
[0]->bits
[index
]);
2952 data
.push_back(RTLIL::State::Sx
);
2954 newNode
= mkconst_bits(data
, false);
2956 if (children
.size() == 0)
2957 newNode
= current_scope
[str
]->children
[0]->clone();
2959 if (current_scope
[str
]->children
[0]->isConst())
2960 newNode
= current_scope
[str
]->children
[0]->clone();
2962 else if (at_zero
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_WIRE
|| current_scope
[str
]->type
== AST_AUTOWIRE
)) {
2963 newNode
= mkconst_int(0, sign_hint
, width_hint
);
2967 if (children
[0]->type
== AST_CONSTANT
) {
2968 RTLIL::Const y
= RTLIL::const_not(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
2969 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2973 case AST_TO_UNSIGNED
:
2974 if (children
[0]->type
== AST_CONSTANT
) {
2975 RTLIL::Const y
= children
[0]->bitsAsConst(width_hint
, sign_hint
);
2976 newNode
= mkconst_bits(y
.bits
, type
== AST_TO_SIGNED
);
2979 if (0) { case AST_BIT_AND
: const_func
= RTLIL::const_and
; }
2980 if (0) { case AST_BIT_OR
: const_func
= RTLIL::const_or
; }
2981 if (0) { case AST_BIT_XOR
: const_func
= RTLIL::const_xor
; }
2982 if (0) { case AST_BIT_XNOR
: const_func
= RTLIL::const_xnor
; }
2983 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2984 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
2985 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
2986 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2989 if (0) { case AST_REDUCE_AND
: const_func
= RTLIL::const_reduce_and
; }
2990 if (0) { case AST_REDUCE_OR
: const_func
= RTLIL::const_reduce_or
; }
2991 if (0) { case AST_REDUCE_XOR
: const_func
= RTLIL::const_reduce_xor
; }
2992 if (0) { case AST_REDUCE_XNOR
: const_func
= RTLIL::const_reduce_xnor
; }
2993 if (0) { case AST_REDUCE_BOOL
: const_func
= RTLIL::const_reduce_bool
; }
2994 if (children
[0]->type
== AST_CONSTANT
) {
2995 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), dummy_arg
, false, false, -1);
2996 newNode
= mkconst_bits(y
.bits
, false);
3000 if (children
[0]->type
== AST_CONSTANT
) {
3001 RTLIL::Const y
= RTLIL::const_logic_not(RTLIL::Const(children
[0]->bits
), dummy_arg
, children
[0]->is_signed
, false, -1);
3002 newNode
= mkconst_bits(y
.bits
, false);
3004 if (children
[0]->isConst()) {
3005 newNode
= mkconst_int(children
[0]->asReal(sign_hint
) == 0, false, 1);
3008 if (0) { case AST_LOGIC_AND
: const_func
= RTLIL::const_logic_and
; }
3009 if (0) { case AST_LOGIC_OR
: const_func
= RTLIL::const_logic_or
; }
3010 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3011 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), RTLIL::Const(children
[1]->bits
),
3012 children
[0]->is_signed
, children
[1]->is_signed
, -1);
3013 newNode
= mkconst_bits(y
.bits
, false);
3015 if (children
[0]->isConst() && children
[1]->isConst()) {
3016 if (type
== AST_LOGIC_AND
)
3017 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) && (children
[1]->asReal(sign_hint
) != 0), false, 1);
3019 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) || (children
[1]->asReal(sign_hint
) != 0), false, 1);
3022 if (0) { case AST_SHIFT_LEFT
: const_func
= RTLIL::const_shl
; }
3023 if (0) { case AST_SHIFT_RIGHT
: const_func
= RTLIL::const_shr
; }
3024 if (0) { case AST_SHIFT_SLEFT
: const_func
= RTLIL::const_sshl
; }
3025 if (0) { case AST_SHIFT_SRIGHT
: const_func
= RTLIL::const_sshr
; }
3026 if (0) { case AST_POW
: const_func
= RTLIL::const_pow
; }
3027 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3028 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3029 RTLIL::Const(children
[1]->bits
), sign_hint
, type
== AST_POW
? children
[1]->is_signed
: false, width_hint
);
3030 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3032 if (type
== AST_POW
&& children
[0]->isConst() && children
[1]->isConst()) {
3033 newNode
= new AstNode(AST_REALVALUE
);
3034 newNode
->realvalue
= pow(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
));
3037 if (0) { case AST_LT
: const_func
= RTLIL::const_lt
; }
3038 if (0) { case AST_LE
: const_func
= RTLIL::const_le
; }
3039 if (0) { case AST_EQ
: const_func
= RTLIL::const_eq
; }
3040 if (0) { case AST_NE
: const_func
= RTLIL::const_ne
; }
3041 if (0) { case AST_EQX
: const_func
= RTLIL::const_eqx
; }
3042 if (0) { case AST_NEX
: const_func
= RTLIL::const_nex
; }
3043 if (0) { case AST_GE
: const_func
= RTLIL::const_ge
; }
3044 if (0) { case AST_GT
: const_func
= RTLIL::const_gt
; }
3045 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3046 int cmp_width
= max(children
[0]->bits
.size(), children
[1]->bits
.size());
3047 bool cmp_signed
= children
[0]->is_signed
&& children
[1]->is_signed
;
3048 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(cmp_width
, cmp_signed
),
3049 children
[1]->bitsAsConst(cmp_width
, cmp_signed
), cmp_signed
, cmp_signed
, 1);
3050 newNode
= mkconst_bits(y
.bits
, false);
3052 if (children
[0]->isConst() && children
[1]->isConst()) {
3053 bool cmp_signed
= (children
[0]->type
== AST_REALVALUE
|| children
[0]->is_signed
) && (children
[1]->type
== AST_REALVALUE
|| children
[1]->is_signed
);
3055 case AST_LT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) < children
[1]->asReal(cmp_signed
), false, 1); break;
3056 case AST_LE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) <= children
[1]->asReal(cmp_signed
), false, 1); break;
3057 case AST_EQ
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
3058 case AST_NE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
3059 case AST_EQX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
3060 case AST_NEX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
3061 case AST_GE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) >= children
[1]->asReal(cmp_signed
), false, 1); break;
3062 case AST_GT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) > children
[1]->asReal(cmp_signed
), false, 1); break;
3063 default: log_abort();
3067 if (0) { case AST_ADD
: const_func
= RTLIL::const_add
; }
3068 if (0) { case AST_SUB
: const_func
= RTLIL::const_sub
; }
3069 if (0) { case AST_MUL
: const_func
= RTLIL::const_mul
; }
3070 if (0) { case AST_DIV
: const_func
= RTLIL::const_div
; }
3071 if (0) { case AST_MOD
: const_func
= RTLIL::const_mod
; }
3072 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
3073 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
3074 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
3075 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3077 if (children
[0]->isConst() && children
[1]->isConst()) {
3078 newNode
= new AstNode(AST_REALVALUE
);
3080 case AST_ADD
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) + children
[1]->asReal(sign_hint
); break;
3081 case AST_SUB
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) - children
[1]->asReal(sign_hint
); break;
3082 case AST_MUL
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) * children
[1]->asReal(sign_hint
); break;
3083 case AST_DIV
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) / children
[1]->asReal(sign_hint
); break;
3084 case AST_MOD
: newNode
->realvalue
= fmod(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
)); break;
3085 default: log_abort();
3089 if (0) { case AST_SELFSZ
: const_func
= RTLIL::const_pos
; }
3090 if (0) { case AST_POS
: const_func
= RTLIL::const_pos
; }
3091 if (0) { case AST_NEG
: const_func
= RTLIL::const_neg
; }
3092 if (children
[0]->type
== AST_CONSTANT
) {
3093 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
3094 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3096 if (children
[0]->isConst()) {
3097 newNode
= new AstNode(AST_REALVALUE
);
3098 if (type
== AST_NEG
)
3099 newNode
->realvalue
= -children
[0]->asReal(sign_hint
);
3101 newNode
->realvalue
= +children
[0]->asReal(sign_hint
);
3105 if (children
[0]->isConst())
3107 bool found_sure_true
= false;
3108 bool found_maybe_true
= false;
3110 if (children
[0]->type
== AST_CONSTANT
)
3111 for (auto &bit
: children
[0]->bits
) {
3112 if (bit
== RTLIL::State::S1
)
3113 found_sure_true
= true;
3114 if (bit
> RTLIL::State::S1
)
3115 found_maybe_true
= true;
3118 found_sure_true
= children
[0]->asReal(sign_hint
) != 0;
3120 AstNode
*choice
= NULL
, *not_choice
= NULL
;
3121 if (found_sure_true
)
3122 choice
= children
[1], not_choice
= children
[2];
3123 else if (!found_maybe_true
)
3124 choice
= children
[2], not_choice
= children
[1];
3126 if (choice
!= NULL
) {
3127 if (choice
->type
== AST_CONSTANT
) {
3128 int other_width_hint
= width_hint
;
3129 bool other_sign_hint
= sign_hint
, other_real
= false;
3130 not_choice
->detectSignWidth(other_width_hint
, other_sign_hint
, &other_real
);
3132 newNode
= new AstNode(AST_REALVALUE
);
3133 choice
->detectSignWidth(width_hint
, sign_hint
);
3134 newNode
->realvalue
= choice
->asReal(sign_hint
);
3136 RTLIL::Const y
= choice
->bitsAsConst(width_hint
, sign_hint
);
3137 if (choice
->is_string
&& y
.bits
.size() % 8 == 0 && sign_hint
== false)
3138 newNode
= mkconst_str(y
.bits
);
3140 newNode
= mkconst_bits(y
.bits
, sign_hint
);
3143 if (choice
->isConst()) {
3144 newNode
= choice
->clone();
3146 } else if (children
[1]->type
== AST_CONSTANT
&& children
[2]->type
== AST_CONSTANT
) {
3147 RTLIL::Const a
= children
[1]->bitsAsConst(width_hint
, sign_hint
);
3148 RTLIL::Const b
= children
[2]->bitsAsConst(width_hint
, sign_hint
);
3149 log_assert(a
.bits
.size() == b
.bits
.size());
3150 for (size_t i
= 0; i
< a
.bits
.size(); i
++)
3151 if (a
.bits
[i
] != b
.bits
[i
])
3152 a
.bits
[i
] = RTLIL::State::Sx
;
3153 newNode
= mkconst_bits(a
.bits
, sign_hint
);
3154 } else if (children
[1]->isConst() && children
[2]->isConst()) {
3155 newNode
= new AstNode(AST_REALVALUE
);
3156 if (children
[1]->asReal(sign_hint
) == children
[2]->asReal(sign_hint
))
3157 newNode
->realvalue
= children
[1]->asReal(sign_hint
);
3159 // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
3160 // the data type in question should be returned if the ?: is ambiguous. The
3161 // value in Table 7-1 for the 'real' type is 0.0.
3162 newNode
->realvalue
= 0.0;
3167 string_op
= !children
.empty();
3168 for (auto it
= children
.begin(); it
!= children
.end(); it
++) {
3169 if ((*it
)->type
!= AST_CONSTANT
)
3171 if (!(*it
)->is_string
)
3173 tmp_bits
.insert(tmp_bits
.end(), (*it
)->bits
.begin(), (*it
)->bits
.end());
3175 newNode
= string_op
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
3178 if (children
.at(0)->type
!= AST_CONSTANT
|| children
.at(1)->type
!= AST_CONSTANT
)
3180 for (int i
= 0; i
< children
[0]->bitsAsConst().as_int(); i
++)
3181 tmp_bits
.insert(tmp_bits
.end(), children
.at(1)->bits
.begin(), children
.at(1)->bits
.end());
3182 newNode
= children
.at(1)->is_string
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
3190 // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
3193 // fprintf(stderr, "----\n");
3194 // dumpAst(stderr, "- ");
3195 // newNode->dumpAst(stderr, "+ ");
3196 log_assert(newNode
!= NULL
);
3197 newNode
->filename
= filename
;
3198 newNode
->location
= location
;
3199 newNode
->cloneInto(this);
3201 did_something
= true;
3207 recursion_counter
--;
3208 return did_something
;
3211 static void replace_result_wire_name_in_function(AstNode
*node
, std::string
&from
, std::string
&to
)
3213 for (auto &it
: node
->children
)
3214 replace_result_wire_name_in_function(it
, from
, to
);
3215 if (node
->str
== from
)
3219 // replace a readmem[bh] TCALL ast node with a block of memory assignments
3220 AstNode
*AstNode::readmem(bool is_readmemh
, std::string mem_filename
, AstNode
*memory
, int start_addr
, int finish_addr
, bool unconditional_init
)
3222 int mem_width
, mem_size
, addr_bits
;
3223 memory
->meminfo(mem_width
, mem_size
, addr_bits
);
3225 AstNode
*block
= new AstNode(AST_BLOCK
);
3227 AstNode
*meminit
= nullptr;
3228 int next_meminit_cursor
=0;
3229 vector
<State
> meminit_bits
;
3233 f
.open(mem_filename
.c_str());
3240 std::string path
= filename
.substr(0, filename
.find_last_of(slash
)+1);
3241 f
.open(path
+ mem_filename
.c_str());
3242 yosys_input_files
.insert(path
+ mem_filename
);
3244 yosys_input_files
.insert(mem_filename
);
3246 if (f
.fail() || GetSize(mem_filename
) == 0)
3247 log_file_error(filename
, location
.first_line
, "Can not open file `%s` for %s.\n", mem_filename
.c_str(), str
.c_str());
3249 log_assert(GetSize(memory
->children
) == 2 && memory
->children
[1]->type
== AST_RANGE
&& memory
->children
[1]->range_valid
);
3250 int range_left
= memory
->children
[1]->range_left
, range_right
= memory
->children
[1]->range_right
;
3251 int range_min
= min(range_left
, range_right
), range_max
= max(range_left
, range_right
);
3254 start_addr
= range_min
;
3256 if (finish_addr
< 0)
3257 finish_addr
= range_max
+ 1;
3259 bool in_comment
= false;
3260 int increment
= start_addr
<= finish_addr
? +1 : -1;
3261 int cursor
= start_addr
;
3265 std::string line
, token
;
3266 std::getline(f
, line
);
3268 for (int i
= 0; i
< GetSize(line
); i
++) {
3269 if (in_comment
&& line
.compare(i
, 2, "*/") == 0) {
3275 if (!in_comment
&& line
.compare(i
, 2, "/*") == 0)
3283 token
= next_token(line
, " \t\r\n");
3284 if (token
.empty() || token
.compare(0, 2, "//") == 0)
3287 if (token
[0] == '@') {
3288 token
= token
.substr(1);
3289 const char *nptr
= token
.c_str();
3291 cursor
= strtol(nptr
, &endptr
, 16);
3292 if (!*nptr
|| *endptr
)
3293 log_file_error(filename
, location
.first_line
, "Can not parse address `%s` for %s.\n", nptr
, str
.c_str());
3297 AstNode
*value
= VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width
, is_readmemh
? 'h' : 'b') + token
);
3299 if (unconditional_init
)
3301 if (meminit
== nullptr || cursor
!= next_meminit_cursor
)
3303 if (meminit
!= nullptr) {
3304 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
3305 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
3308 meminit
= new AstNode(AST_MEMINIT
);
3309 meminit
->children
.push_back(AstNode::mkconst_int(cursor
, false));
3310 meminit
->children
.push_back(nullptr);
3311 meminit
->children
.push_back(nullptr);
3312 meminit
->str
= memory
->str
;
3313 meminit
->id2ast
= memory
;
3314 meminit_bits
.clear();
3317 current_ast_mod
->children
.push_back(meminit
);
3318 next_meminit_cursor
= cursor
;
3322 next_meminit_cursor
++;
3323 meminit_bits
.insert(meminit_bits
.end(), value
->bits
.begin(), value
->bits
.end());
3328 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
, false))), value
));
3329 block
->children
.back()->children
[0]->str
= memory
->str
;
3330 block
->children
.back()->children
[0]->id2ast
= memory
;
3331 block
->children
.back()->children
[0]->was_checked
= true;
3334 cursor
+= increment
;
3335 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
3339 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
3343 if (meminit
!= nullptr) {
3344 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
3345 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
3351 // annotate the names of all wires and other named objects in a generate block
3352 void AstNode::expand_genblock(std::string index_var
, std::string prefix
, std::map
<std::string
, std::string
> &name_map
)
3354 if (!index_var
.empty() && type
== AST_IDENTIFIER
&& str
== index_var
) {
3355 if (children
.empty()) {
3356 current_scope
[index_var
]->children
[0]->cloneInto(this);
3358 AstNode
*p
= new AstNode(AST_LOCALPARAM
, current_scope
[index_var
]->children
[0]->clone());
3359 p
->str
= stringf("$genval$%d", autoidx
++);
3360 current_ast_mod
->children
.push_back(p
);
3366 if ((type
== AST_IDENTIFIER
|| type
== AST_FCALL
|| type
== AST_TCALL
|| type
== AST_WIRETYPE
) && name_map
.count(str
) > 0)
3367 str
= name_map
[str
];
3369 std::map
<std::string
, std::string
> backup_name_map
;
3371 for (size_t i
= 0; i
< children
.size(); i
++) {
3372 AstNode
*child
= children
[i
];
3373 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
||
3374 child
->type
== AST_FUNCTION
|| child
->type
== AST_TASK
|| child
->type
== AST_CELL
|| child
->type
== AST_TYPEDEF
|| child
->type
== AST_ENUM_ITEM
) {
3375 if (backup_name_map
.size() == 0)
3376 backup_name_map
= name_map
;
3377 std::string new_name
= prefix
[0] == '\\' ? prefix
.substr(1) : prefix
;
3378 size_t pos
= child
->str
.rfind('.');
3379 if (pos
== std::string::npos
)
3380 pos
= child
->str
[0] == '\\' && prefix
[0] == '\\' ? 1 : 0;
3383 new_name
= child
->str
.substr(0, pos
) + new_name
+ child
->str
.substr(pos
);
3384 if (new_name
[0] != '$' && new_name
[0] != '\\')
3385 new_name
= prefix
[0] + new_name
;
3386 name_map
[child
->str
] = new_name
;
3387 if (child
->type
== AST_FUNCTION
)
3388 replace_result_wire_name_in_function(child
, child
->str
, new_name
);
3390 child
->str
= new_name
;
3391 current_scope
[new_name
] = child
;
3393 if (child
->type
== AST_ENUM
){
3394 current_scope
[child
->str
] = child
;
3395 for (auto enode
: child
->children
){
3396 log_assert(enode
->type
== AST_ENUM_ITEM
);
3397 if (backup_name_map
.size() == 0)
3398 backup_name_map
= name_map
;
3399 std::string new_name
= prefix
[0] == '\\' ? prefix
.substr(1) : prefix
;
3400 size_t pos
= enode
->str
.rfind('.');
3401 if (pos
== std::string::npos
)
3402 pos
= enode
->str
[0] == '\\' && prefix
[0] == '\\' ? 1 : 0;
3405 new_name
= enode
->str
.substr(0, pos
) + new_name
+ enode
->str
.substr(pos
);
3406 if (new_name
[0] != '$' && new_name
[0] != '\\')
3407 new_name
= prefix
[0] + new_name
;
3408 name_map
[enode
->str
] = new_name
;
3410 enode
->str
= new_name
;
3411 current_scope
[new_name
] = enode
;
3416 for (size_t i
= 0; i
< children
.size(); i
++) {
3417 AstNode
*child
= children
[i
];
3418 // AST_PREFIX member names should not be prefixed; a nested AST_PREFIX
3419 // still needs to recursed-into
3420 if (type
== AST_PREFIX
&& i
== 1 && child
->type
== AST_IDENTIFIER
)
3422 if (child
->type
!= AST_FUNCTION
&& child
->type
!= AST_TASK
)
3423 child
->expand_genblock(index_var
, prefix
, name_map
);
3427 if (backup_name_map
.size() > 0)
3428 name_map
.swap(backup_name_map
);
3431 // rename stuff (used when tasks of functions are instantiated)
3432 void AstNode::replace_ids(const std::string
&prefix
, const std::map
<std::string
, std::string
> &rules
)
3434 if (type
== AST_BLOCK
)
3436 std::map
<std::string
, std::string
> new_rules
= rules
;
3437 std::string new_prefix
= prefix
+ str
;
3439 for (auto child
: children
)
3440 if (child
->type
== AST_WIRE
) {
3441 new_rules
[child
->str
] = new_prefix
+ child
->str
;
3442 child
->str
= new_prefix
+ child
->str
;
3445 for (auto child
: children
)
3446 if (child
->type
!= AST_WIRE
)
3447 child
->replace_ids(new_prefix
, new_rules
);
3451 if (type
== AST_IDENTIFIER
&& rules
.count(str
) > 0)
3452 str
= rules
.at(str
);
3453 for (auto child
: children
)
3454 child
->replace_ids(prefix
, rules
);
3458 // helper function for mem2reg_as_needed_pass1
3459 static void mark_memories_assign_lhs_complex(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
3460 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, AstNode
*that
)
3462 for (auto &child
: that
->children
)
3463 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, child
);
3465 if (that
->type
== AST_IDENTIFIER
&& that
->id2ast
&& that
->id2ast
->type
== AST_MEMORY
) {
3466 AstNode
*mem
= that
->id2ast
;
3467 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_CMPLX_LHS
))
3468 mem2reg_places
[mem
].insert(stringf("%s:%d", that
->filename
.c_str(), that
->location
.first_line
));
3469 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CMPLX_LHS
;
3473 // find memories that should be replaced by registers
3474 void AstNode::mem2reg_as_needed_pass1(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
3475 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, dict
<AstNode
*, uint32_t> &proc_flags
, uint32_t &flags
)
3477 uint32_t children_flags
= 0;
3478 int lhs_children_counter
= 0;
3480 if (type
== AST_TYPEDEF
)
3481 return; // don't touch content of typedefs
3483 if (type
== AST_ASSIGN
|| type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
)
3485 // mark all memories that are used in a complex expression on the left side of an assignment
3486 for (auto &lhs_child
: children
[0]->children
)
3487 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, lhs_child
);
3489 if (children
[0]->type
== AST_IDENTIFIER
&& children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
)
3491 AstNode
*mem
= children
[0]->id2ast
;
3493 // activate mem2reg if this is assigned in an async proc
3494 if (flags
& AstNode::MEM2REG_FL_ASYNC
) {
3495 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ASYNC
))
3496 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3497 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ASYNC
;
3500 // remember if this is assigned blocking (=)
3501 if (type
== AST_ASSIGN_EQ
) {
3502 if (!(proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
))
3503 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3504 proc_flags
[mem
] |= AstNode::MEM2REG_FL_EQ1
;
3507 // for proper (non-init) writes: remember if this is a constant index or not
3508 if ((flags
& MEM2REG_FL_INIT
) == 0) {
3509 if (children
[0]->children
.size() && children
[0]->children
[0]->type
== AST_RANGE
&& children
[0]->children
[0]->children
.size()) {
3510 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
)
3511 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CONST_LHS
;
3513 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_VAR_LHS
;
3517 // remember where this is
3518 if (flags
& MEM2REG_FL_INIT
) {
3519 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_INIT
))
3520 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3521 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_INIT
;
3523 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ELSE
))
3524 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3525 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ELSE
;
3529 lhs_children_counter
= 1;
3532 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
)
3534 AstNode
*mem
= id2ast
;
3536 // flag if used after blocking assignment (in same proc)
3537 if ((proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
) && !(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_EQ2
)) {
3538 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), location
.first_line
));
3539 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_EQ2
;
3543 // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg'
3544 if (type
== AST_MEMORY
&& (get_bool_attribute(ID::mem2reg
) || (flags
& AstNode::MEM2REG_FL_ALL
) || !is_reg
))
3545 mem2reg_candidates
[this] |= AstNode::MEM2REG_FL_FORCED
;
3547 if (type
== AST_MODULE
&& get_bool_attribute(ID::mem2reg
))
3548 children_flags
|= AstNode::MEM2REG_FL_ALL
;
3550 dict
<AstNode
*, uint32_t> *proc_flags_p
= NULL
;
3552 if (type
== AST_ALWAYS
) {
3553 int count_edge_events
= 0;
3554 for (auto child
: children
)
3555 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
3556 count_edge_events
++;
3557 if (count_edge_events
!= 1)
3558 children_flags
|= AstNode::MEM2REG_FL_ASYNC
;
3559 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
3562 if (type
== AST_INITIAL
) {
3563 children_flags
|= AstNode::MEM2REG_FL_INIT
;
3564 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
3567 uint32_t backup_flags
= flags
;
3568 flags
|= children_flags
;
3569 log_assert((flags
& ~0x000000ff) == 0);
3571 for (auto child
: children
)
3573 if (lhs_children_counter
> 0) {
3574 lhs_children_counter
--;
3575 if (child
->children
.size() && child
->children
[0]->type
== AST_RANGE
&& child
->children
[0]->children
.size()) {
3576 for (auto c
: child
->children
[0]->children
) {
3578 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
3580 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
3585 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
3587 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
3590 flags
&= ~children_flags
| backup_flags
;
3594 for (auto it
: *proc_flags_p
)
3595 log_assert((it
.second
& ~0xff000000) == 0);
3597 delete proc_flags_p
;
3601 bool AstNode::mem2reg_check(pool
<AstNode
*> &mem2reg_set
)
3603 if (type
!= AST_IDENTIFIER
|| !id2ast
|| !mem2reg_set
.count(id2ast
))
3606 if (children
.empty() || children
[0]->type
!= AST_RANGE
|| GetSize(children
[0]->children
) != 1)
3607 log_file_error(filename
, location
.first_line
, "Invalid array access.\n");
3612 void AstNode::mem2reg_remove(pool
<AstNode
*> &mem2reg_set
, vector
<AstNode
*> &delnodes
)
3614 log_assert(mem2reg_set
.count(this) == 0);
3616 if (mem2reg_set
.count(id2ast
))
3619 for (size_t i
= 0; i
< children
.size(); i
++) {
3620 if (mem2reg_set
.count(children
[i
]) > 0) {
3621 delnodes
.push_back(children
[i
]);
3622 children
.erase(children
.begin() + (i
--));
3624 children
[i
]->mem2reg_remove(mem2reg_set
, delnodes
);
3629 // actually replace memories with registers
3630 bool AstNode::mem2reg_as_needed_pass2(pool
<AstNode
*> &mem2reg_set
, AstNode
*mod
, AstNode
*block
, AstNode
*&async_block
)
3632 bool did_something
= false;
3634 if (type
== AST_BLOCK
)
3637 if (type
== AST_FUNCTION
|| type
== AST_TASK
)
3640 if (type
== AST_TYPEDEF
)
3643 if (type
== AST_MEMINIT
&& id2ast
&& mem2reg_set
.count(id2ast
))
3645 log_assert(children
[0]->type
== AST_CONSTANT
);
3646 log_assert(children
[1]->type
== AST_CONSTANT
);
3647 log_assert(children
[2]->type
== AST_CONSTANT
);
3649 int cursor
= children
[0]->asInt(false);
3650 Const data
= children
[1]->bitsAsConst();
3651 int length
= children
[2]->asInt(false);
3655 AstNode
*block
= new AstNode(AST_INITIAL
, new AstNode(AST_BLOCK
));
3656 mod
->children
.push_back(block
);
3657 block
= block
->children
[0];
3659 int wordsz
= GetSize(data
) / length
;
3661 for (int i
= 0; i
< length
; i
++) {
3662 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)));
3663 block
->children
.back()->children
[0]->str
= str
;
3664 block
->children
.back()->children
[0]->id2ast
= id2ast
;
3665 block
->children
.back()->children
[0]->was_checked
= true;
3669 AstNode
*newNode
= new AstNode(AST_NONE
);
3670 newNode
->cloneInto(this);
3673 did_something
= true;
3676 if (type
== AST_ASSIGN
&& block
== NULL
&& children
[0]->mem2reg_check(mem2reg_set
))
3678 if (async_block
== NULL
) {
3679 async_block
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
3680 mod
->children
.push_back(async_block
);
3683 AstNode
*newNode
= clone();
3684 newNode
->type
= AST_ASSIGN_EQ
;
3685 newNode
->children
[0]->was_checked
= true;
3686 async_block
->children
[0]->children
.push_back(newNode
);
3688 newNode
= new AstNode(AST_NONE
);
3689 newNode
->cloneInto(this);
3692 did_something
= true;
3695 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->mem2reg_check(mem2reg_set
) &&
3696 children
[0]->children
[0]->children
[0]->type
!= AST_CONSTANT
)
3698 std::stringstream sstr
;
3699 sstr
<< "$mem2reg_wr$" << children
[0]->str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
3700 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
3702 int mem_width
, mem_size
, addr_bits
;
3703 bool mem_signed
= children
[0]->id2ast
->is_signed
;
3704 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
3706 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
3707 wire_addr
->str
= id_addr
;
3708 wire_addr
->is_reg
= true;
3709 wire_addr
->was_checked
= true;
3710 wire_addr
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
3711 mod
->children
.push_back(wire_addr
);
3712 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
3714 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
3715 wire_data
->str
= id_data
;
3716 wire_data
->is_reg
= true;
3717 wire_data
->was_checked
= true;
3718 wire_data
->is_signed
= mem_signed
;
3719 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
3720 mod
->children
.push_back(wire_data
);
3721 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
3723 log_assert(block
!= NULL
);
3724 size_t assign_idx
= 0;
3725 while (assign_idx
< block
->children
.size() && block
->children
[assign_idx
] != this)
3727 log_assert(assign_idx
< block
->children
.size());
3729 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
3730 assign_addr
->children
[0]->str
= id_addr
;
3731 assign_addr
->children
[0]->was_checked
= true;
3732 block
->children
.insert(block
->children
.begin()+assign_idx
+1, assign_addr
);
3734 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
3735 case_node
->children
[0]->str
= id_addr
;
3736 for (int i
= 0; i
< mem_size
; i
++) {
3737 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->children
[0]->integer
) != i
)
3739 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
3740 AstNode
*assign_reg
= new AstNode(type
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
3741 if (children
[0]->children
.size() == 2)
3742 assign_reg
->children
[0]->children
.push_back(children
[0]->children
[1]->clone());
3743 assign_reg
->children
[0]->str
= stringf("%s[%d]", children
[0]->str
.c_str(), i
);
3744 assign_reg
->children
[1]->str
= id_data
;
3745 cond_node
->children
[1]->children
.push_back(assign_reg
);
3746 case_node
->children
.push_back(cond_node
);
3748 block
->children
.insert(block
->children
.begin()+assign_idx
+2, case_node
);
3750 children
[0]->delete_children();
3751 children
[0]->range_valid
= false;
3752 children
[0]->id2ast
= NULL
;
3753 children
[0]->str
= id_data
;
3754 type
= AST_ASSIGN_EQ
;
3755 children
[0]->was_checked
= true;
3757 did_something
= true;
3760 if (mem2reg_check(mem2reg_set
))
3762 AstNode
*bit_part_sel
= NULL
;
3763 if (children
.size() == 2)
3764 bit_part_sel
= children
[1]->clone();
3766 if (children
[0]->children
[0]->type
== AST_CONSTANT
)
3768 int id
= children
[0]->children
[0]->integer
;
3769 str
= stringf("%s[%d]", str
.c_str(), id
);
3772 range_valid
= false;
3777 std::stringstream sstr
;
3778 sstr
<< "$mem2reg_rd$" << str
<< "$" << filename
<< ":" << location
.first_line
<< "$" << (autoidx
++);
3779 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
3781 int mem_width
, mem_size
, addr_bits
;
3782 bool mem_signed
= id2ast
->is_signed
;
3783 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
3785 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
3786 wire_addr
->str
= id_addr
;
3787 wire_addr
->is_reg
= true;
3788 wire_addr
->was_checked
= true;
3790 wire_addr
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
3791 mod
->children
.push_back(wire_addr
);
3792 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
3794 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
3795 wire_data
->str
= id_data
;
3796 wire_data
->is_reg
= true;
3797 wire_data
->was_checked
= true;
3798 wire_data
->is_signed
= mem_signed
;
3800 wire_data
->attributes
[ID::nosync
] = AstNode::mkconst_int(1, false);
3801 mod
->children
.push_back(wire_data
);
3802 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
3804 AstNode
*assign_addr
= new AstNode(block
? AST_ASSIGN_EQ
: AST_ASSIGN
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->clone());
3805 assign_addr
->children
[0]->str
= id_addr
;
3806 assign_addr
->children
[0]->was_checked
= true;
3808 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
3809 case_node
->children
[0]->str
= id_addr
;
3811 for (int i
= 0; i
< mem_size
; i
++) {
3812 if (children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->integer
) != i
)
3814 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
3815 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
3816 assign_reg
->children
[0]->str
= id_data
;
3817 assign_reg
->children
[0]->was_checked
= true;
3818 assign_reg
->children
[1]->str
= stringf("%s[%d]", str
.c_str(), i
);
3819 cond_node
->children
[1]->children
.push_back(assign_reg
);
3820 case_node
->children
.push_back(cond_node
);
3823 std::vector
<RTLIL::State
> x_bits
;
3824 for (int i
= 0; i
< mem_width
; i
++)
3825 x_bits
.push_back(RTLIL::State::Sx
);
3827 AstNode
*cond_node
= new AstNode(AST_COND
, new AstNode(AST_DEFAULT
), new AstNode(AST_BLOCK
));
3828 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), AstNode::mkconst_bits(x_bits
, false));
3829 assign_reg
->children
[0]->str
= id_data
;
3830 assign_reg
->children
[0]->was_checked
= true;
3831 cond_node
->children
[1]->children
.push_back(assign_reg
);
3832 case_node
->children
.push_back(cond_node
);
3836 size_t assign_idx
= 0;
3837 while (assign_idx
< block
->children
.size() && !block
->children
[assign_idx
]->contains(this))
3839 log_assert(assign_idx
< block
->children
.size());
3840 block
->children
.insert(block
->children
.begin()+assign_idx
, case_node
);
3841 block
->children
.insert(block
->children
.begin()+assign_idx
, assign_addr
);
3845 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
3846 proc
->children
[0]->children
.push_back(case_node
);
3847 mod
->children
.push_back(proc
);
3848 mod
->children
.push_back(assign_addr
);
3852 range_valid
= false;
3858 children
.push_back(bit_part_sel
);
3860 did_something
= true;
3863 log_assert(id2ast
== NULL
|| mem2reg_set
.count(id2ast
) == 0);
3865 auto children_list
= children
;
3866 for (size_t i
= 0; i
< children_list
.size(); i
++)
3867 if (children_list
[i
]->mem2reg_as_needed_pass2(mem2reg_set
, mod
, block
, async_block
))
3868 did_something
= true;
3870 return did_something
;
3873 // calculate memory dimensions
3874 void AstNode::meminfo(int &mem_width
, int &mem_size
, int &addr_bits
)
3876 log_assert(type
== AST_MEMORY
);
3878 mem_width
= children
[0]->range_left
- children
[0]->range_right
+ 1;
3879 mem_size
= children
[1]->range_left
- children
[1]->range_right
;
3883 mem_size
+= min(children
[1]->range_left
, children
[1]->range_right
) + 1;
3886 while ((1 << addr_bits
) < mem_size
)
3890 bool AstNode::has_const_only_constructs(bool &recommend_const_eval
)
3892 if (type
== AST_FOR
)
3893 recommend_const_eval
= true;
3894 if (type
== AST_WHILE
|| type
== AST_REPEAT
)
3896 if (type
== AST_FCALL
&& current_scope
.count(str
))
3897 if (current_scope
[str
]->has_const_only_constructs(recommend_const_eval
))
3899 for (auto child
: children
)
3900 if (child
->AstNode::has_const_only_constructs(recommend_const_eval
))
3905 bool AstNode::is_simple_const_expr()
3907 if (type
== AST_IDENTIFIER
)
3909 for (auto child
: children
)
3910 if (!child
->is_simple_const_expr())
3915 // helper function for AstNode::eval_const_function()
3916 void AstNode::replace_variables(std::map
<std::string
, AstNode::varinfo_t
> &variables
, AstNode
*fcall
)
3918 if (type
== AST_IDENTIFIER
&& variables
.count(str
)) {
3919 int offset
= variables
.at(str
).offset
, width
= variables
.at(str
).val
.bits
.size();
3920 if (!children
.empty()) {
3921 if (children
.size() != 1 || children
.at(0)->type
!= AST_RANGE
)
3922 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",
3923 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
3924 children
.at(0)->replace_variables(variables
, fcall
);
3925 while (simplify(true, false, false, 1, -1, false, true)) { }
3926 if (!children
.at(0)->range_valid
)
3927 log_file_error(filename
, location
.first_line
, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
3928 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
3929 offset
= min(children
.at(0)->range_left
, children
.at(0)->range_right
);
3930 width
= min(std::abs(children
.at(0)->range_left
- children
.at(0)->range_right
) + 1, width
);
3932 offset
-= variables
.at(str
).offset
;
3933 std::vector
<RTLIL::State
> &var_bits
= variables
.at(str
).val
.bits
;
3934 std::vector
<RTLIL::State
> new_bits(var_bits
.begin() + offset
, var_bits
.begin() + offset
+ width
);
3935 AstNode
*newNode
= mkconst_bits(new_bits
, variables
.at(str
).is_signed
);
3936 newNode
->cloneInto(this);
3941 for (auto &child
: children
)
3942 child
->replace_variables(variables
, fcall
);
3945 // evaluate functions with all-const arguments
3946 AstNode
*AstNode::eval_const_function(AstNode
*fcall
)
3948 std::map
<std::string
, AstNode
*> backup_scope
;
3949 std::map
<std::string
, AstNode::varinfo_t
> variables
;
3950 AstNode
*block
= new AstNode(AST_BLOCK
);
3953 for (auto child
: children
)
3955 if (child
->type
== AST_WIRE
)
3957 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
3958 if (!child
->range_valid
)
3959 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",
3960 child
->str
.c_str(), fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
3961 variables
[child
->str
].val
= RTLIL::Const(RTLIL::State::Sx
, abs(child
->range_left
- child
->range_right
)+1);
3962 variables
[child
->str
].offset
= min(child
->range_left
, child
->range_right
);
3963 variables
[child
->str
].is_signed
= child
->is_signed
;
3964 if (child
->is_input
&& argidx
< fcall
->children
.size())
3965 variables
[child
->str
].val
= fcall
->children
.at(argidx
++)->bitsAsConst(variables
[child
->str
].val
.bits
.size());
3966 backup_scope
[child
->str
] = current_scope
[child
->str
];
3967 current_scope
[child
->str
] = child
;
3971 block
->children
.push_back(child
->clone());
3974 log_assert(variables
.count(str
) != 0);
3976 while (!block
->children
.empty())
3978 AstNode
*stmt
= block
->children
.front();
3981 log("-----------------------------------\n");
3982 for (auto &it
: variables
)
3983 log("%20s %40s\n", it
.first
.c_str(), log_signal(it
.second
.val
));
3984 stmt
->dumpAst(NULL
, "stmt> ");
3987 if (stmt
->type
== AST_ASSIGN_EQ
)
3989 if (stmt
->children
.at(0)->type
== AST_IDENTIFIER
&& stmt
->children
.at(0)->children
.size() != 0 &&
3990 stmt
->children
.at(0)->children
.at(0)->type
== AST_RANGE
)
3991 stmt
->children
.at(0)->children
.at(0)->replace_variables(variables
, fcall
);
3992 stmt
->children
.at(1)->replace_variables(variables
, fcall
);
3993 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
3995 if (stmt
->type
!= AST_ASSIGN_EQ
)
3998 if (stmt
->children
.at(1)->type
!= AST_CONSTANT
)
3999 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",
4000 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4002 if (stmt
->children
.at(0)->type
!= AST_IDENTIFIER
)
4003 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",
4004 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4006 if (!variables
.count(stmt
->children
.at(0)->str
))
4007 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",
4008 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4010 if (stmt
->children
.at(0)->children
.empty()) {
4011 variables
[stmt
->children
.at(0)->str
].val
= stmt
->children
.at(1)->bitsAsConst(variables
[stmt
->children
.at(0)->str
].val
.bits
.size());
4013 AstNode
*range
= stmt
->children
.at(0)->children
.at(0);
4014 if (!range
->range_valid
)
4015 log_file_error(range
->filename
, range
->location
.first_line
, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
4016 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4017 int offset
= min(range
->range_left
, range
->range_right
);
4018 int width
= std::abs(range
->range_left
- range
->range_right
) + 1;
4019 varinfo_t
&v
= variables
[stmt
->children
.at(0)->str
];
4020 RTLIL::Const r
= stmt
->children
.at(1)->bitsAsConst(v
.val
.bits
.size());
4021 for (int i
= 0; i
< width
; i
++)
4022 v
.val
.bits
.at(i
+offset
-v
.offset
) = r
.bits
.at(i
);
4025 delete block
->children
.front();
4026 block
->children
.erase(block
->children
.begin());
4030 if (stmt
->type
== AST_FOR
)
4032 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(0));
4033 stmt
->children
.at(3)->children
.push_back(stmt
->children
.at(2));
4034 stmt
->children
.erase(stmt
->children
.begin() + 2);
4035 stmt
->children
.erase(stmt
->children
.begin());
4036 stmt
->type
= AST_WHILE
;
4040 if (stmt
->type
== AST_WHILE
)
4042 AstNode
*cond
= stmt
->children
.at(0)->clone();
4043 cond
->replace_variables(variables
, fcall
);
4044 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
4046 if (cond
->type
!= AST_CONSTANT
)
4047 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",
4048 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4050 if (cond
->asBool()) {
4051 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
4053 delete block
->children
.front();
4054 block
->children
.erase(block
->children
.begin());
4061 if (stmt
->type
== AST_REPEAT
)
4063 AstNode
*num
= stmt
->children
.at(0)->clone();
4064 num
->replace_variables(variables
, fcall
);
4065 while (num
->simplify(true, false, false, 1, -1, false, true)) { }
4067 if (num
->type
!= AST_CONSTANT
)
4068 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",
4069 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4071 block
->children
.erase(block
->children
.begin());
4072 for (int i
= 0; i
< num
->bitsAsConst().as_int(); i
++)
4073 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
4080 if (stmt
->type
== AST_CASE
)
4082 AstNode
*expr
= stmt
->children
.at(0)->clone();
4083 expr
->replace_variables(variables
, fcall
);
4084 while (expr
->simplify(true, false, false, 1, -1, false, true)) { }
4086 AstNode
*sel_case
= NULL
;
4087 for (size_t i
= 1; i
< stmt
->children
.size(); i
++)
4089 bool found_match
= false;
4090 log_assert(stmt
->children
.at(i
)->type
== AST_COND
|| stmt
->children
.at(i
)->type
== AST_CONDX
|| stmt
->children
.at(i
)->type
== AST_CONDZ
);
4092 if (stmt
->children
.at(i
)->children
.front()->type
== AST_DEFAULT
) {
4093 sel_case
= stmt
->children
.at(i
)->children
.back();
4097 for (size_t j
= 0; j
+1 < stmt
->children
.at(i
)->children
.size() && !found_match
; j
++)
4099 AstNode
*cond
= stmt
->children
.at(i
)->children
.at(j
)->clone();
4100 cond
->replace_variables(variables
, fcall
);
4102 cond
= new AstNode(AST_EQ
, expr
->clone(), cond
);
4103 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
4105 if (cond
->type
!= AST_CONSTANT
)
4106 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",
4107 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4109 found_match
= cond
->asBool();
4114 sel_case
= stmt
->children
.at(i
)->children
.back();
4119 block
->children
.erase(block
->children
.begin());
4121 block
->children
.insert(block
->children
.begin(), sel_case
->clone());
4127 if (stmt
->type
== AST_BLOCK
)
4129 block
->children
.erase(block
->children
.begin());
4130 block
->children
.insert(block
->children
.begin(), stmt
->children
.begin(), stmt
->children
.end());
4131 stmt
->children
.clear();
4136 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",
4137 fcall
->filename
.c_str(), fcall
->location
.first_line
, fcall
->location
.first_column
, fcall
->location
.last_line
, fcall
->location
.last_column
);
4143 for (auto &it
: backup_scope
)
4144 if (it
.second
== NULL
)
4145 current_scope
.erase(it
.first
);
4147 current_scope
[it
.first
] = it
.second
;
4149 return AstNode::mkconst_bits(variables
.at(str
).val
.bits
, variables
.at(str
).is_signed
);
4152 void AstNode::allocateDefaultEnumValues()
4154 log_assert(type
==AST_ENUM
);
4155 int last_enum_int
= -1;
4156 for (auto node
: children
) {
4157 log_assert(node
->type
==AST_ENUM_ITEM
);
4158 node
->attributes
[ID::enum_base_type
] = mkconst_str(str
);
4159 for (size_t i
= 0; i
< node
->children
.size(); i
++) {
4160 switch (node
->children
[i
]->type
) {
4162 // replace with auto-incremented constant
4163 delete node
->children
[i
];
4164 node
->children
[i
] = AstNode::mkconst_int(++last_enum_int
, true);
4167 // explicit constant (or folded expression)
4168 // TODO: can't extend 'x or 'z item
4169 last_enum_int
= node
->children
[i
]->integer
;
4175 // TODO: range check