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
, linenum
, "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
67 // Simplify the argument
68 AstNode
*node_arg
= nullptr;
70 // Everything from here on depends on the format specifier
79 if (next_arg
>= GetSize(children
))
80 log_file_error(filename
, linenum
, "Missing argument for %%%c format specifier in system task `%s'.\n",
81 cformat
, str
.c_str());
83 node_arg
= children
[next_arg
++];
84 while (node_arg
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
85 if (node_arg
->type
!= AST_CONSTANT
)
86 log_file_error(filename
, linenum
, "Failed to evaluate system task `%s' with non-constant argument.\n", str
.c_str());
94 log_file_error(filename
, linenum
, "System task `%s' called with invalid/unsupported format specifier.\n", str
.c_str());
102 sout
+= node_arg
->bitsAsConst().decode_string();
109 snprintf(tmp
, sizeof(tmp
), "%d", node_arg
->bitsAsConst().as_int());
118 snprintf(tmp
, sizeof(tmp
), "%x", node_arg
->bitsAsConst().as_int());
125 sout
+= log_id(current_module
->name
);
133 // not a format specifier
141 // convert the AST into a simpler AST that has all parameters substituted by their
142 // values, unrolled for-loops, expanded generate blocks, etc. when this function
143 // is done with an AST it can be converted into RTLIL using genRTLIL().
145 // this function also does all name resolving and sets the id2ast member of all
146 // nodes that link to a different node using names and lexical scoping.
147 bool AstNode::simplify(bool const_fold
, bool at_zero
, bool in_lvalue
, int stage
, int width_hint
, bool sign_hint
, bool in_param
)
149 static int recursion_counter
= 0;
150 static bool deep_recursion_warning
= false;
152 if (recursion_counter
++ == 1000 && deep_recursion_warning
) {
153 log_warning("Deep recursion in AST simplifier.\nDoes this design contain insanely long expressions?\n");
154 deep_recursion_warning
= false;
157 AstNode
*newNode
= NULL
;
158 bool did_something
= false;
161 log("-------------\n");
162 log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage
, recursion_counter
, filename
.c_str(), linenum
, type2str(type
).c_str(), this);
163 log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
164 int(const_fold
), int(at_zero
), int(in_lvalue
), int(stage
), int(width_hint
), int(sign_hint
), int(in_param
));
165 // dumpAst(NULL, "> ");
170 log_assert(type
== AST_MODULE
|| type
== AST_INTERFACE
);
172 deep_recursion_warning
= true;
173 while (simplify(const_fold
, at_zero
, in_lvalue
, 1, width_hint
, sign_hint
, in_param
)) { }
175 if (!flag_nomem2reg
&& !get_bool_attribute("\\nomem2reg"))
177 dict
<AstNode
*, pool
<std::string
>> mem2reg_places
;
178 dict
<AstNode
*, uint32_t> mem2reg_candidates
, dummy_proc_flags
;
179 uint32_t flags
= flag_mem2reg
? AstNode::MEM2REG_FL_ALL
: 0;
180 mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, dummy_proc_flags
, flags
);
182 pool
<AstNode
*> mem2reg_set
;
183 for (auto &it
: mem2reg_candidates
)
185 AstNode
*mem
= it
.first
;
186 uint32_t memflags
= it
.second
;
187 bool this_nomeminit
= flag_nomeminit
;
188 log_assert((memflags
& ~0x00ffff00) == 0);
190 if (mem
->get_bool_attribute("\\nomem2reg"))
193 if (mem
->get_bool_attribute("\\nomeminit") || get_bool_attribute("\\nomeminit"))
194 this_nomeminit
= true;
196 if (memflags
& AstNode::MEM2REG_FL_FORCED
)
197 goto silent_activate
;
199 if (memflags
& AstNode::MEM2REG_FL_EQ2
)
200 goto verbose_activate
;
202 if (memflags
& AstNode::MEM2REG_FL_SET_ASYNC
)
203 goto verbose_activate
;
205 if ((memflags
& AstNode::MEM2REG_FL_SET_INIT
) && (memflags
& AstNode::MEM2REG_FL_SET_ELSE
) && this_nomeminit
)
206 goto verbose_activate
;
208 if (memflags
& AstNode::MEM2REG_FL_CMPLX_LHS
)
209 goto verbose_activate
;
211 if ((memflags
& AstNode::MEM2REG_FL_CONST_LHS
) && !(memflags
& AstNode::MEM2REG_FL_VAR_LHS
))
212 goto verbose_activate
;
214 // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
218 if (mem2reg_set
.count(mem
) == 0) {
219 std::string message
= stringf("Replacing memory %s with list of registers.", mem
->str
.c_str());
220 bool first_element
= true;
221 for (auto &place
: mem2reg_places
[it
.first
]) {
222 message
+= stringf("%s%s", first_element
? " See " : ", ", place
.c_str());
223 first_element
= false;
225 log_warning("%s\n", message
.c_str());
229 // log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
230 mem2reg_set
.insert(mem
);
233 for (auto node
: mem2reg_set
)
235 int mem_width
, mem_size
, addr_bits
;
236 node
->meminfo(mem_width
, mem_size
, addr_bits
);
238 int data_range_left
= node
->children
[0]->range_left
;
239 int data_range_right
= node
->children
[0]->range_right
;
241 if (node
->children
[0]->range_swapped
)
242 std::swap(data_range_left
, data_range_right
);
244 for (int i
= 0; i
< mem_size
; i
++) {
245 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
246 mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
247 reg
->str
= stringf("%s[%d]", node
->str
.c_str(), i
);
249 reg
->is_signed
= node
->is_signed
;
250 for (auto &it
: node
->attributes
)
251 if (it
.first
!= ID(mem2reg
))
252 reg
->attributes
.emplace(it
.first
, it
.second
->clone());
253 reg
->filename
= node
->filename
;
254 reg
->linenum
= node
->linenum
;
255 children
.push_back(reg
);
256 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
260 AstNode
*async_block
= NULL
;
261 while (mem2reg_as_needed_pass2(mem2reg_set
, this, NULL
, async_block
)) { }
263 vector
<AstNode
*> delnodes
;
264 mem2reg_remove(mem2reg_set
, delnodes
);
266 for (auto node
: delnodes
)
270 while (simplify(const_fold
, at_zero
, in_lvalue
, 2, width_hint
, sign_hint
, in_param
)) { }
275 current_filename
= filename
;
276 set_line_num(linenum
);
278 // we do not look inside a task or function
279 // (but as soon as a task or function is instantiated we process the generated AST as usual)
280 if (type
== AST_FUNCTION
|| type
== AST_TASK
) {
285 // deactivate all calls to non-synthesis system tasks
286 // note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
287 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && (str
== "$strobe" || str
== "$monitor" || str
== "$time" ||
288 str
== "$dumpfile" || str
== "$dumpvars" || str
== "$dumpon" || str
== "$dumpoff" || str
== "$dumpall")) {
289 log_file_warning(filename
, linenum
, "Ignoring call to system %s %s.\n", type
== AST_FCALL
? "function" : "task", str
.c_str());
294 if ((type
== AST_TCALL
) && (str
== "$display" || str
== "$write") && (!current_always
|| current_always
->type
!= AST_INITIAL
)) {
295 log_file_warning(filename
, linenum
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
300 // print messages if this a call to $display() or $write()
301 // This code implements only a small subset of Verilog-2005 $display() format specifiers,
302 // but should be good enough for most uses
303 if ((type
== AST_TCALL
) && ((str
== "$display") || (str
== "$write")))
305 int nargs
= GetSize(children
);
307 log_file_error(filename
, linenum
, "System task `%s' got %d arguments, expected >= 1.\n",
308 str
.c_str(), int(children
.size()));
310 // First argument is the format string
311 AstNode
*node_string
= children
[0];
312 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
313 if (node_string
->type
!= AST_CONSTANT
)
314 log_file_error(filename
, linenum
, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str
.c_str());
315 std::string sformat
= node_string
->bitsAsConst().decode_string();
316 std::string sout
= process_format_str(sformat
, 1, stage
, width_hint
, sign_hint
);
317 // Finally, print the message (only include a \n for $display, not for $write)
318 log("%s", sout
.c_str());
319 if (str
== "$display")
325 // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
326 if (type
== AST_WIRE
|| type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_RANGE
|| type
== AST_PREFIX
|| type
== AST_TYPEDEF
)
328 if (type
== AST_IDENTIFIER
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
))
331 // in certain cases a function must be evaluated constant. this is what in_param controls.
332 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
|| type
== AST_DEFPARAM
|| type
== AST_PARASET
|| type
== AST_PREFIX
)
335 std::map
<std::string
, AstNode
*> backup_scope
;
337 // create name resolution entries for all objects with names
338 // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
339 if (type
== AST_MODULE
) {
340 current_scope
.clear();
341 std::map
<std::string
, AstNode
*> this_wire_scope
;
342 for (size_t i
= 0; i
< children
.size(); i
++) {
343 AstNode
*node
= children
[i
];
345 if (node
->type
== AST_WIRE
) {
346 if (node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
347 for (auto c
: node
->children
[0]->children
) {
348 if (!c
->is_simple_const_expr()) {
349 if (attributes
.count("\\dynports"))
350 delete attributes
.at("\\dynports");
351 attributes
["\\dynports"] = AstNode::mkconst_int(1, true);
355 if (this_wire_scope
.count(node
->str
) > 0) {
356 AstNode
*first_node
= this_wire_scope
[node
->str
];
357 if (first_node
->is_input
&& node
->is_reg
)
358 goto wires_are_incompatible
;
359 if (!node
->is_input
&& !node
->is_output
&& node
->is_reg
&& node
->children
.size() == 0)
360 goto wires_are_compatible
;
361 if (first_node
->children
.size() == 0 && node
->children
.size() == 1 && node
->children
[0]->type
== AST_RANGE
) {
362 AstNode
*r
= node
->children
[0];
363 if (r
->range_valid
&& r
->range_left
== 0 && r
->range_right
== 0) {
365 node
->children
.pop_back();
368 if (first_node
->children
.size() != node
->children
.size())
369 goto wires_are_incompatible
;
370 for (size_t j
= 0; j
< node
->children
.size(); j
++) {
371 AstNode
*n1
= first_node
->children
[j
], *n2
= node
->children
[j
];
372 if (n1
->type
== AST_RANGE
&& n2
->type
== AST_RANGE
&& n1
->range_valid
&& n2
->range_valid
) {
373 if (n1
->range_left
!= n2
->range_left
)
374 goto wires_are_incompatible
;
375 if (n1
->range_right
!= n2
->range_right
)
376 goto wires_are_incompatible
;
377 } else if (*n1
!= *n2
)
378 goto wires_are_incompatible
;
380 if (first_node
->range_left
!= node
->range_left
)
381 goto wires_are_incompatible
;
382 if (first_node
->range_right
!= node
->range_right
)
383 goto wires_are_incompatible
;
384 if (first_node
->port_id
== 0 && (node
->is_input
|| node
->is_output
))
385 goto wires_are_incompatible
;
386 wires_are_compatible
:
388 first_node
->is_input
= true;
390 first_node
->is_output
= true;
392 first_node
->is_reg
= true;
394 first_node
->is_logic
= true;
396 first_node
->is_signed
= true;
397 for (auto &it
: node
->attributes
) {
398 if (first_node
->attributes
.count(it
.first
) > 0)
399 delete first_node
->attributes
[it
.first
];
400 first_node
->attributes
[it
.first
] = it
.second
->clone();
402 children
.erase(children
.begin()+(i
--));
403 did_something
= true;
406 wires_are_incompatible
:
408 log_file_error(filename
, linenum
, "Incompatible re-declaration of wire %s.\n", node
->str
.c_str());
411 this_wire_scope
[node
->str
] = node
;
413 if (node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
414 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
|| node
->type
== AST_CELL
||
415 node
->type
== AST_TYPEDEF
) {
416 backup_scope
[node
->str
] = current_scope
[node
->str
];
417 current_scope
[node
->str
] = node
;
420 for (size_t i
= 0; i
< children
.size(); i
++) {
421 AstNode
*node
= children
[i
];
422 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
)
423 while (node
->simplify(true, false, false, 1, -1, false, node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
))
424 did_something
= true;
428 auto backup_current_block
= current_block
;
429 auto backup_current_block_child
= current_block_child
;
430 auto backup_current_top_block
= current_top_block
;
431 auto backup_current_always
= current_always
;
432 auto backup_current_always_clocked
= current_always_clocked
;
434 if (type
== AST_ALWAYS
|| type
== AST_INITIAL
)
436 if (current_always
!= nullptr)
437 log_file_error(filename
, linenum
, "Invalid nesting of always blocks and/or initializations.\n");
439 current_always
= this;
440 current_always_clocked
= false;
442 if (type
== AST_ALWAYS
)
443 for (auto child
: children
) {
444 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
445 current_always_clocked
= true;
446 if (child
->type
== AST_EDGE
&& GetSize(child
->children
) == 1 &&
447 child
->children
[0]->type
== AST_IDENTIFIER
&& child
->children
[0]->str
== "\\$global_clock")
448 current_always_clocked
= true;
452 int backup_width_hint
= width_hint
;
453 bool backup_sign_hint
= sign_hint
;
455 bool detect_width_simple
= false;
456 bool child_0_is_self_determined
= false;
457 bool child_1_is_self_determined
= false;
458 bool child_2_is_self_determined
= false;
459 bool children_are_self_determined
= false;
460 bool reset_width_after_children
= false;
467 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, true, stage
, -1, false, in_param
) == true)
468 did_something
= true;
469 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, in_param
) == true)
470 did_something
= true;
471 children
[0]->detectSignWidth(backup_width_hint
, backup_sign_hint
);
472 children
[1]->detectSignWidth(width_hint
, sign_hint
);
473 width_hint
= max(width_hint
, backup_width_hint
);
474 child_0_is_self_determined
= true;
475 // test only once, before optimizations and memory mappings but after assignment LHS was mapped to an identifier
476 if (children
[0]->id2ast
&& !children
[0]->was_checked
) {
477 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->id2ast
->is_logic
)
478 children
[0]->id2ast
->is_reg
= true; // if logic type is used in a block asignment
479 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && !children
[0]->id2ast
->is_reg
)
480 log_warning("wire '%s' is assigned in a block at %s:%d.\n", children
[0]->str
.c_str(), filename
.c_str(), linenum
);
481 if (type
== AST_ASSIGN
&& children
[0]->id2ast
->is_reg
) {
482 bool is_rand_reg
= false;
483 if (children
[1]->type
== AST_FCALL
) {
484 if (children
[1]->str
== "\\$anyconst")
486 if (children
[1]->str
== "\\$anyseq")
488 if (children
[1]->str
== "\\$allconst")
490 if (children
[1]->str
== "\\$allseq")
494 log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children
[0]->str
.c_str(), filename
.c_str(), linenum
);
496 children
[0]->was_checked
= true;
502 while (!children
[0]->basic_prep
&& children
[0]->simplify(false, false, false, stage
, -1, false, true) == true)
503 did_something
= true;
504 children
[0]->detectSignWidth(width_hint
, sign_hint
);
505 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
506 while (!children
[1]->basic_prep
&& children
[1]->simplify(false, false, false, stage
, -1, false, true) == true)
507 did_something
= true;
508 if (!children
[1]->range_valid
)
509 log_file_error(filename
, linenum
, "Non-constant width range on parameter decl.\n");
510 width_hint
= max(width_hint
, children
[1]->range_left
- children
[1]->range_right
+ 1);
516 case AST_TO_UNSIGNED
:
522 case AST_REDUCE_XNOR
:
523 case AST_REDUCE_BOOL
:
524 detect_width_simple
= true;
525 children_are_self_determined
= true;
540 detect_width_simple
= true;
544 case AST_SHIFT_RIGHT
:
545 case AST_SHIFT_SLEFT
:
546 case AST_SHIFT_SRIGHT
:
548 detect_width_simple
= true;
549 child_1_is_self_determined
= true;
562 for (auto child
: children
) {
563 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
564 did_something
= true;
565 child
->detectSignWidthWorker(width_hint
, sign_hint
);
567 reset_width_after_children
= true;
573 detect_width_simple
= true;
574 children_are_self_determined
= true;
578 detect_width_simple
= true;
579 child_0_is_self_determined
= true;
583 detect_width_simple
= true;
584 children_are_self_determined
= true;
589 children_are_self_determined
= true;
597 if (detect_width_simple
&& width_hint
< 0) {
598 if (type
== AST_REPLICATE
)
599 while (children
[0]->simplify(true, false, in_lvalue
, stage
, -1, false, true) == true)
600 did_something
= true;
601 for (auto child
: children
)
602 while (!child
->basic_prep
&& child
->simplify(false, false, in_lvalue
, stage
, -1, false, in_param
) == true)
603 did_something
= true;
604 detectSignWidth(width_hint
, sign_hint
);
607 if (type
== AST_FCALL
&& str
== "\\$past")
608 detectSignWidth(width_hint
, sign_hint
);
610 if (type
== AST_TERNARY
) {
611 int width_hint_left
, width_hint_right
;
612 bool sign_hint_left
, sign_hint_right
;
613 bool found_real_left
, found_real_right
;
614 children
[1]->detectSignWidth(width_hint_left
, sign_hint_left
, &found_real_left
);
615 children
[2]->detectSignWidth(width_hint_right
, sign_hint_right
, &found_real_right
);
616 if (found_real_left
|| found_real_right
) {
617 child_1_is_self_determined
= true;
618 child_2_is_self_determined
= true;
622 if (type
== AST_CONDX
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
623 for (auto &bit
: children
.at(0)->bits
)
624 if (bit
== State::Sz
|| bit
== State::Sx
)
628 if (type
== AST_CONDZ
&& children
.size() > 0 && children
.at(0)->type
== AST_CONSTANT
) {
629 for (auto &bit
: children
.at(0)->bits
)
630 if (bit
== State::Sz
)
634 if (const_fold
&& type
== AST_CASE
)
636 while (children
[0]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
637 if (children
[0]->type
== AST_CONSTANT
&& children
[0]->bits_only_01()) {
638 std::vector
<AstNode
*> new_children
;
639 new_children
.push_back(children
[0]);
640 for (int i
= 1; i
< GetSize(children
); i
++) {
641 AstNode
*child
= children
[i
];
642 log_assert(child
->type
== AST_COND
|| child
->type
== AST_CONDX
|| child
->type
== AST_CONDZ
);
643 for (auto v
: child
->children
) {
644 if (v
->type
== AST_DEFAULT
)
645 goto keep_const_cond
;
646 if (v
->type
== AST_BLOCK
)
648 while (v
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) { }
649 if (v
->type
== AST_CONSTANT
&& v
->bits_only_01()) {
650 if (v
->bits
== children
[0]->bits
) {
651 while (i
+1 < GetSize(children
))
652 delete children
[++i
];
653 goto keep_const_cond
;
657 goto keep_const_cond
;
661 new_children
.push_back(child
);
665 new_children
.swap(children
);
669 // simplify all children first
670 // (iterate by index as e.g. auto wires can add new children in the process)
671 for (size_t i
= 0; i
< children
.size(); i
++) {
672 bool did_something_here
= true;
673 bool backup_flag_autowire
= flag_autowire
;
674 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && i
>= 3)
676 if ((type
== AST_GENIF
|| type
== AST_GENCASE
) && i
>= 1)
678 if (type
== AST_GENBLOCK
)
680 if (type
== AST_BLOCK
&& !str
.empty())
682 if (type
== AST_PREFIX
&& i
>= 1)
684 if (type
== AST_DEFPARAM
&& i
== 0)
685 flag_autowire
= true;
686 while (did_something_here
&& i
< children
.size()) {
687 bool const_fold_here
= const_fold
, in_lvalue_here
= in_lvalue
;
688 int width_hint_here
= width_hint
;
689 bool sign_hint_here
= sign_hint
;
690 bool in_param_here
= in_param
;
691 if (i
== 0 && (type
== AST_REPLICATE
|| type
== AST_WIRE
))
692 const_fold_here
= true, in_param_here
= true;
693 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
)
694 const_fold_here
= true;
695 if (i
== 0 && (type
== AST_ASSIGN
|| type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
))
696 in_lvalue_here
= true;
697 if (type
== AST_BLOCK
) {
698 current_block
= this;
699 current_block_child
= children
[i
];
701 if ((type
== AST_ALWAYS
|| type
== AST_INITIAL
) && children
[i
]->type
== AST_BLOCK
)
702 current_top_block
= children
[i
];
703 if (i
== 0 && child_0_is_self_determined
)
704 width_hint_here
= -1, sign_hint_here
= false;
705 if (i
== 1 && child_1_is_self_determined
)
706 width_hint_here
= -1, sign_hint_here
= false;
707 if (i
== 2 && child_2_is_self_determined
)
708 width_hint_here
= -1, sign_hint_here
= false;
709 if (children_are_self_determined
)
710 width_hint_here
= -1, sign_hint_here
= false;
711 did_something_here
= children
[i
]->simplify(const_fold_here
, at_zero
, in_lvalue_here
, stage
, width_hint_here
, sign_hint_here
, in_param_here
);
712 if (did_something_here
)
713 did_something
= true;
715 if (stage
== 2 && children
[i
]->type
== AST_INITIAL
&& current_ast_mod
!= this) {
716 current_ast_mod
->children
.push_back(children
[i
]);
717 children
.erase(children
.begin() + (i
--));
718 did_something
= true;
720 flag_autowire
= backup_flag_autowire
;
722 for (auto &attr
: attributes
) {
723 while (attr
.second
->simplify(true, false, false, stage
, -1, false, true))
724 did_something
= true;
727 if (reset_width_after_children
) {
728 width_hint
= backup_width_hint
;
729 sign_hint
= backup_sign_hint
;
731 detectSignWidth(width_hint
, sign_hint
);
734 current_block
= backup_current_block
;
735 current_block_child
= backup_current_block_child
;
736 current_top_block
= backup_current_top_block
;
737 current_always
= backup_current_always
;
738 current_always_clocked
= backup_current_always_clocked
;
740 for (auto it
= backup_scope
.begin(); it
!= backup_scope
.end(); it
++) {
741 if (it
->second
== NULL
)
742 current_scope
.erase(it
->first
);
744 current_scope
[it
->first
] = it
->second
;
747 current_filename
= filename
;
748 set_line_num(linenum
);
750 if (type
== AST_MODULE
)
751 current_scope
.clear();
753 // convert defparam nodes to cell parameters
754 if (type
== AST_DEFPARAM
&& !children
.empty())
756 if (children
[0]->type
!= AST_IDENTIFIER
)
757 log_file_error(filename
, linenum
, "Module name in defparam contains non-constant expressions!\n");
759 string modname
, paramname
= children
[0]->str
;
761 size_t pos
= paramname
.rfind('.');
763 while (pos
!= 0 && pos
!= std::string::npos
)
765 modname
= paramname
.substr(0, pos
);
767 if (current_scope
.count(modname
))
770 pos
= paramname
.rfind('.', pos
- 1);
773 if (pos
== std::string::npos
)
774 log_file_error(filename
, linenum
, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname
).c_str());
776 paramname
= "\\" + paramname
.substr(pos
+1);
778 if (current_scope
.at(modname
)->type
!= AST_CELL
)
779 log_file_error(filename
, linenum
, "Defparam argument `%s . %s` does not match a cell!\n",
780 RTLIL::unescape_id(modname
).c_str(), RTLIL::unescape_id(paramname
).c_str());
782 AstNode
*paraset
= new AstNode(AST_PARASET
, children
[1]->clone(), GetSize(children
) > 2 ? children
[2]->clone() : NULL
);
783 paraset
->str
= paramname
;
785 AstNode
*cell
= current_scope
.at(modname
);
786 cell
->children
.insert(cell
->children
.begin() + 1, paraset
);
791 if (type
== AST_TYPEDEF
) {
792 log_assert(children
.size() == 1);
793 log_assert(children
[0]->type
== AST_WIRE
|| children
[0]->type
== AST_MEMORY
);
794 while(children
[0]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
))
795 did_something
= true;
796 log_assert(!children
[0]->is_custom_type
);
799 // resolve types of wires
800 if (type
== AST_WIRE
|| type
== AST_MEMORY
) {
801 if (is_custom_type
) {
802 log_assert(children
.size() >= 1);
803 log_assert(children
[0]->type
== AST_WIRETYPE
);
804 if (!current_scope
.count(children
[0]->str
))
805 log_file_error(filename
, linenum
, "Unknown identifier `%s' used as type name\n", children
[0]->str
.c_str());
806 AstNode
*resolved_type
= current_scope
.at(children
[0]->str
);
807 if (resolved_type
->type
!= AST_TYPEDEF
)
808 log_file_error(filename
, linenum
, "`%s' does not name a type\n", children
[0]->str
.c_str());
809 log_assert(resolved_type
->children
.size() == 1);
810 AstNode
*templ
= resolved_type
->children
[0];
811 // Remove type reference
813 children
.erase(children
.begin());
815 // Ensure typedef itself is fully simplified
816 while(templ
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
818 if (type
== AST_WIRE
)
820 is_reg
= templ
->is_reg
;
821 is_logic
= templ
->is_logic
;
822 is_signed
= templ
->is_signed
;
823 is_string
= templ
->is_string
;
824 is_custom_type
= templ
->is_custom_type
;
826 range_valid
= templ
->range_valid
;
827 range_swapped
= templ
->range_swapped
;
828 range_left
= templ
->range_left
;
829 range_right
= templ
->range_right
;
831 // Insert clones children from template at beginning
832 for (int i
= 0; i
< GetSize(templ
->children
); i
++)
833 children
.insert(children
.begin() + i
, templ
->children
[i
]->clone());
835 if (type
== AST_MEMORY
&& GetSize(children
) == 1) {
836 // Single-bit memories must have [0:0] range
837 AstNode
*rng
= new AstNode(AST_RANGE
);
838 rng
->children
.push_back(AstNode::mkconst_int(0, true));
839 rng
->children
.push_back(AstNode::mkconst_int(0, true));
840 children
.insert(children
.begin(), rng
);
843 did_something
= true;
845 log_assert(!is_custom_type
);
848 // resolve types of parameters
849 if (type
== AST_LOCALPARAM
|| type
== AST_PARAMETER
) {
850 if (is_custom_type
) {
851 log_assert(children
.size() == 2);
852 log_assert(children
[1]->type
== AST_WIRETYPE
);
853 if (!current_scope
.count(children
[1]->str
))
854 log_file_error(filename
, linenum
, "Unknown identifier `%s' used as type name\n", children
[1]->str
.c_str());
855 AstNode
*resolved_type
= current_scope
.at(children
[1]->str
);
856 if (resolved_type
->type
!= AST_TYPEDEF
)
857 log_file_error(filename
, linenum
, "`%s' does not name a type\n", children
[1]->str
.c_str());
858 log_assert(resolved_type
->children
.size() == 1);
859 AstNode
*templ
= resolved_type
->children
[0];
863 // Ensure typedef itself is fully simplified
864 while(templ
->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
)) {};
866 if (templ
->type
== AST_MEMORY
)
867 log_file_error(filename
, linenum
, "unpacked array type `%s' cannot be used for a parameter\n", children
[1]->str
.c_str());
868 is_signed
= templ
->is_signed
;
869 is_string
= templ
->is_string
;
870 is_custom_type
= templ
->is_custom_type
;
872 range_valid
= templ
->range_valid
;
873 range_swapped
= templ
->range_swapped
;
874 range_left
= templ
->range_left
;
875 range_right
= templ
->range_right
;
876 for (auto template_child
: templ
->children
)
877 children
.push_back(template_child
->clone());
878 did_something
= true;
880 log_assert(!is_custom_type
);
883 // resolve constant prefixes
884 if (type
== AST_PREFIX
) {
885 if (children
[0]->type
!= AST_CONSTANT
) {
886 // dumpAst(NULL, "> ");
887 log_file_error(filename
, linenum
, "Index in generate block prefix syntax is not constant!\n");
889 if (children
[1]->type
== AST_PREFIX
)
890 children
[1]->simplify(const_fold
, at_zero
, in_lvalue
, stage
, width_hint
, sign_hint
, in_param
);
891 log_assert(children
[1]->type
== AST_IDENTIFIER
);
892 newNode
= children
[1]->clone();
893 const char *second_part
= children
[1]->str
.c_str();
894 if (second_part
[0] == '\\')
896 newNode
->str
= stringf("%s[%d].%s", str
.c_str(), children
[0]->integer
, second_part
);
900 // evaluate TO_BITS nodes
901 if (type
== AST_TO_BITS
) {
902 if (children
[0]->type
!= AST_CONSTANT
)
903 log_file_error(filename
, linenum
, "Left operand of to_bits expression is not constant!\n");
904 if (children
[1]->type
!= AST_CONSTANT
)
905 log_file_error(filename
, linenum
, "Right operand of to_bits expression is not constant!\n");
906 RTLIL::Const new_value
= children
[1]->bitsAsConst(children
[0]->bitsAsConst().as_int(), children
[1]->is_signed
);
907 newNode
= mkconst_bits(new_value
.bits
, children
[1]->is_signed
);
911 // annotate constant ranges
912 if (type
== AST_RANGE
) {
913 bool old_range_valid
= range_valid
;
915 range_swapped
= false;
918 log_assert(children
.size() >= 1);
919 if (children
[0]->type
== AST_CONSTANT
) {
921 range_left
= children
[0]->integer
;
922 if (children
.size() == 1)
923 range_right
= range_left
;
925 if (children
.size() >= 2) {
926 if (children
[1]->type
== AST_CONSTANT
)
927 range_right
= children
[1]->integer
;
931 if (old_range_valid
!= range_valid
)
932 did_something
= true;
933 if (range_valid
&& range_left
>= 0 && range_right
> range_left
) {
934 int tmp
= range_right
;
935 range_right
= range_left
;
937 range_swapped
= true;
941 // annotate wires with their ranges
942 if (type
== AST_WIRE
) {
943 if (children
.size() > 0) {
944 if (children
[0]->range_valid
) {
946 did_something
= true;
948 range_swapped
= children
[0]->range_swapped
;
949 range_left
= children
[0]->range_left
;
950 range_right
= children
[0]->range_right
;
954 did_something
= true;
956 range_swapped
= false;
962 // resolve multiranges on memory decl
963 if (type
== AST_MEMORY
&& children
.size() > 1 && children
[1]->type
== AST_MULTIRANGE
)
966 multirange_dimensions
.clear();
967 for (auto range
: children
[1]->children
) {
968 if (!range
->range_valid
)
969 log_file_error(filename
, linenum
, "Non-constant range on memory decl.\n");
970 multirange_dimensions
.push_back(min(range
->range_left
, range
->range_right
));
971 multirange_dimensions
.push_back(max(range
->range_left
, range
->range_right
) - min(range
->range_left
, range
->range_right
) + 1);
972 total_size
*= multirange_dimensions
.back();
975 children
[1] = new AstNode(AST_RANGE
, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size
-1, true));
976 did_something
= true;
979 // resolve multiranges on memory access
980 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
&& children
.size() > 0 && children
[0]->type
== AST_MULTIRANGE
)
982 AstNode
*index_expr
= nullptr;
984 for (int i
= 0; 2*i
< GetSize(id2ast
->multirange_dimensions
); i
++)
986 if (GetSize(children
[0]->children
) < i
)
987 log_file_error(filename
, linenum
, "Insufficient number of array indices for %s.\n", log_id(str
));
989 AstNode
*new_index_expr
= children
[0]->children
[i
]->children
.at(0)->clone();
991 if (id2ast
->multirange_dimensions
[2*i
])
992 new_index_expr
= new AstNode(AST_SUB
, new_index_expr
, AstNode::mkconst_int(id2ast
->multirange_dimensions
[2*i
], true));
995 index_expr
= new_index_expr
;
997 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
);
1000 for (int i
= GetSize(id2ast
->multirange_dimensions
)/2; i
< GetSize(children
[0]->children
); i
++)
1001 children
.push_back(children
[0]->children
[i
]->clone());
1004 if (index_expr
== nullptr)
1005 children
.erase(children
.begin());
1007 children
[0] = new AstNode(AST_RANGE
, index_expr
);
1009 did_something
= true;
1012 // trim/extend parameters
1013 if (type
== AST_PARAMETER
|| type
== AST_LOCALPARAM
) {
1014 if (children
.size() > 1 && children
[1]->type
== AST_RANGE
) {
1015 if (!children
[1]->range_valid
)
1016 log_file_error(filename
, linenum
, "Non-constant width range on parameter decl.\n");
1017 int width
= std::abs(children
[1]->range_left
- children
[1]->range_right
) + 1;
1018 if (children
[0]->type
== AST_REALVALUE
) {
1019 RTLIL::Const constvalue
= children
[0]->realAsConst(width
);
1020 log_file_warning(filename
, linenum
, "converting real value %e to binary %s.\n",
1021 children
[0]->realvalue
, log_signal(constvalue
));
1023 children
[0] = mkconst_bits(constvalue
.bits
, sign_hint
);
1024 did_something
= true;
1026 if (children
[0]->type
== AST_CONSTANT
) {
1027 if (width
!= int(children
[0]->bits
.size())) {
1028 RTLIL::SigSpec
sig(children
[0]->bits
);
1029 sig
.extend_u0(width
, children
[0]->is_signed
);
1030 AstNode
*old_child_0
= children
[0];
1031 children
[0] = mkconst_bits(sig
.as_const().bits
, is_signed
);
1034 children
[0]->is_signed
= is_signed
;
1037 range_swapped
= children
[1]->range_swapped
;
1038 range_left
= children
[1]->range_left
;
1039 range_right
= children
[1]->range_right
;
1041 if (children
.size() > 1 && children
[1]->type
== AST_REALVALUE
&& children
[0]->type
== AST_CONSTANT
) {
1042 double as_realvalue
= children
[0]->asReal(sign_hint
);
1044 children
[0] = new AstNode(AST_REALVALUE
);
1045 children
[0]->realvalue
= as_realvalue
;
1046 did_something
= true;
1050 // annotate identifiers using scope resolution and create auto-wires as needed
1051 if (type
== AST_IDENTIFIER
) {
1052 if (current_scope
.count(str
) == 0) {
1053 for (auto node
: current_ast_mod
->children
) {
1054 if ((node
->type
== AST_PARAMETER
|| node
->type
== AST_LOCALPARAM
|| node
->type
== AST_WIRE
|| node
->type
== AST_AUTOWIRE
|| node
->type
== AST_GENVAR
||
1055 node
->type
== AST_MEMORY
|| node
->type
== AST_FUNCTION
|| node
->type
== AST_TASK
|| node
->type
== AST_DPI_FUNCTION
) && str
== node
->str
) {
1056 current_scope
[node
->str
] = node
;
1061 if (current_scope
.count(str
) == 0) {
1062 if (flag_autowire
|| str
== "\\$global_clock") {
1063 AstNode
*auto_wire
= new AstNode(AST_AUTOWIRE
);
1064 auto_wire
->str
= str
;
1065 current_ast_mod
->children
.push_back(auto_wire
);
1066 current_scope
[str
] = auto_wire
;
1067 did_something
= true;
1069 log_file_error(filename
, linenum
, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str
.c_str());
1072 if (id2ast
!= current_scope
[str
]) {
1073 id2ast
= current_scope
[str
];
1074 did_something
= true;
1078 // split memory access with bit select to individual statements
1079 if (type
== AST_IDENTIFIER
&& children
.size() == 2 && children
[0]->type
== AST_RANGE
&& children
[1]->type
== AST_RANGE
&& !in_lvalue
)
1081 if (id2ast
== NULL
|| id2ast
->type
!= AST_MEMORY
|| children
[0]->children
.size() != 1)
1082 log_file_error(filename
, linenum
, "Invalid bit-select on memory access!\n");
1084 int mem_width
, mem_size
, addr_bits
;
1085 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
1087 int data_range_left
= id2ast
->children
[0]->range_left
;
1088 int data_range_right
= id2ast
->children
[0]->range_right
;
1090 if (id2ast
->children
[0]->range_swapped
)
1091 std::swap(data_range_left
, data_range_right
);
1093 std::stringstream sstr
;
1094 sstr
<< "$mem2bits$" << str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1095 std::string wire_id
= sstr
.str();
1097 AstNode
*wire
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(data_range_left
, true), mkconst_int(data_range_right
, true)));
1098 wire
->str
= wire_id
;
1100 wire
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
1101 current_ast_mod
->children
.push_back(wire
);
1102 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
1104 AstNode
*data
= clone();
1105 delete data
->children
[1];
1106 data
->children
.pop_back();
1108 AstNode
*assign
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), data
);
1109 assign
->children
[0]->str
= wire_id
;
1110 assign
->children
[0]->was_checked
= true;
1114 size_t assign_idx
= 0;
1115 while (assign_idx
< current_block
->children
.size() && current_block
->children
[assign_idx
] != current_block_child
)
1117 log_assert(assign_idx
< current_block
->children
.size());
1118 current_block
->children
.insert(current_block
->children
.begin()+assign_idx
, assign
);
1119 wire
->is_reg
= true;
1123 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
1124 proc
->children
[0]->children
.push_back(assign
);
1125 current_ast_mod
->children
.push_back(proc
);
1128 newNode
= new AstNode(AST_IDENTIFIER
, children
[1]->clone());
1129 newNode
->str
= wire_id
;
1130 newNode
->id2ast
= wire
;
1134 if (type
== AST_WHILE
)
1135 log_file_error(filename
, linenum
, "While loops are only allowed in constant functions!\n");
1137 if (type
== AST_REPEAT
)
1139 AstNode
*count
= children
[0];
1140 AstNode
*body
= children
[1];
1142 // eval count expression
1143 while (count
->simplify(true, false, false, stage
, 32, true, false)) { }
1145 if (count
->type
!= AST_CONSTANT
)
1146 log_file_error(filename
, linenum
, "Repeat loops outside must have constant repeat counts!\n");
1148 // convert to a block with the body repeated n times
1151 for (int i
= 0; i
< count
->bitsAsConst().as_int(); i
++)
1152 children
.insert(children
.begin(), body
->clone());
1156 did_something
= true;
1159 // unroll for loops and generate-for blocks
1160 if ((type
== AST_GENFOR
|| type
== AST_FOR
) && children
.size() != 0)
1162 AstNode
*init_ast
= children
[0];
1163 AstNode
*while_ast
= children
[1];
1164 AstNode
*next_ast
= children
[2];
1165 AstNode
*body_ast
= children
[3];
1167 while (body_ast
->type
== AST_GENBLOCK
&& body_ast
->str
.empty() &&
1168 body_ast
->children
.size() == 1 && body_ast
->children
.at(0)->type
== AST_GENBLOCK
)
1169 body_ast
= body_ast
->children
.at(0);
1171 if (init_ast
->type
!= AST_ASSIGN_EQ
)
1172 log_file_error(filename
, linenum
, "Unsupported 1st expression of generate for-loop!\n");
1173 if (next_ast
->type
!= AST_ASSIGN_EQ
)
1174 log_file_error(filename
, linenum
, "Unsupported 3rd expression of generate for-loop!\n");
1176 if (type
== AST_GENFOR
) {
1177 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
1178 log_file_error(filename
, linenum
, "Left hand side of 1st expression of generate for-loop is not a gen var!\n");
1179 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_GENVAR
)
1180 log_file_error(filename
, linenum
, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n");
1182 if (init_ast
->children
[0]->id2ast
== NULL
|| init_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1183 log_file_error(filename
, linenum
, "Left hand side of 1st expression of generate for-loop is not a register!\n");
1184 if (next_ast
->children
[0]->id2ast
== NULL
|| next_ast
->children
[0]->id2ast
->type
!= AST_WIRE
)
1185 log_file_error(filename
, linenum
, "Left hand side of 3rd expression of generate for-loop is not a register!\n");
1188 if (init_ast
->children
[0]->id2ast
!= next_ast
->children
[0]->id2ast
)
1189 log_file_error(filename
, linenum
, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n");
1191 // eval 1st expression
1192 AstNode
*varbuf
= init_ast
->children
[1]->clone();
1194 int expr_width_hint
= -1;
1195 bool expr_sign_hint
= true;
1196 varbuf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1197 while (varbuf
->simplify(true, false, false, stage
, 32, true, false)) { }
1200 if (varbuf
->type
!= AST_CONSTANT
)
1201 log_file_error(filename
, linenum
, "Right hand side of 1st expression of generate for-loop is not constant!\n");
1203 varbuf
= new AstNode(AST_LOCALPARAM
, varbuf
);
1204 varbuf
->str
= init_ast
->children
[0]->str
;
1206 auto resolved
= current_scope
.at(init_ast
->children
[0]->str
);
1207 if (resolved
->range_valid
) {
1208 varbuf
->range_left
= resolved
->range_left
;
1209 varbuf
->range_right
= resolved
->range_right
;
1210 varbuf
->range_swapped
= resolved
->range_swapped
;
1211 varbuf
->range_valid
= resolved
->range_valid
;
1214 AstNode
*backup_scope_varbuf
= current_scope
[varbuf
->str
];
1215 current_scope
[varbuf
->str
] = varbuf
;
1217 size_t current_block_idx
= 0;
1218 if (type
== AST_FOR
) {
1219 while (current_block_idx
< current_block
->children
.size() &&
1220 current_block
->children
[current_block_idx
] != current_block_child
)
1221 current_block_idx
++;
1226 // eval 2nd expression
1227 AstNode
*buf
= while_ast
->clone();
1229 int expr_width_hint
= -1;
1230 bool expr_sign_hint
= true;
1231 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1232 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, false)) { }
1235 if (buf
->type
!= AST_CONSTANT
)
1236 log_file_error(filename
, linenum
, "2nd expression of generate for-loop is not constant!\n");
1238 if (buf
->integer
== 0) {
1245 int index
= varbuf
->children
[0]->integer
;
1246 if (body_ast
->type
== AST_GENBLOCK
)
1247 buf
= body_ast
->clone();
1249 buf
= new AstNode(AST_GENBLOCK
, body_ast
->clone());
1250 if (buf
->str
.empty()) {
1251 std::stringstream sstr
;
1252 sstr
<< "$genblock$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1253 buf
->str
= sstr
.str();
1255 std::map
<std::string
, std::string
> name_map
;
1256 std::stringstream sstr
;
1257 sstr
<< buf
->str
<< "[" << index
<< "].";
1258 buf
->expand_genblock(varbuf
->str
, sstr
.str(), name_map
);
1260 if (type
== AST_GENFOR
) {
1261 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1262 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1263 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1266 for (size_t i
= 0; i
< buf
->children
.size(); i
++)
1267 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
->children
[i
]);
1269 buf
->children
.clear();
1272 // eval 3rd expression
1273 buf
= next_ast
->children
[1]->clone();
1275 int expr_width_hint
= -1;
1276 bool expr_sign_hint
= true;
1277 buf
->detectSignWidth(expr_width_hint
, expr_sign_hint
);
1278 while (buf
->simplify(true, false, false, stage
, expr_width_hint
, expr_sign_hint
, true)) { }
1281 if (buf
->type
!= AST_CONSTANT
)
1282 log_file_error(filename
, linenum
, "Right hand side of 3rd expression of generate for-loop is not constant!\n");
1284 delete varbuf
->children
[0];
1285 varbuf
->children
[0] = buf
;
1288 if (type
== AST_FOR
) {
1289 AstNode
*buf
= next_ast
->clone();
1290 delete buf
->children
[1];
1291 buf
->children
[1] = varbuf
->children
[0]->clone();
1292 current_block
->children
.insert(current_block
->children
.begin() + current_block_idx
++, buf
);
1295 current_scope
[varbuf
->str
] = backup_scope_varbuf
;
1298 did_something
= true;
1301 // check for local objects in unnamed block
1302 if (type
== AST_BLOCK
&& str
.empty())
1304 for (size_t i
= 0; i
< children
.size(); i
++)
1305 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
)
1306 log_file_error(children
[i
]->filename
, children
[i
]->linenum
, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
1309 // transform block with name
1310 if (type
== AST_BLOCK
&& !str
.empty())
1312 std::map
<std::string
, std::string
> name_map
;
1313 expand_genblock(std::string(), str
+ ".", name_map
);
1315 std::vector
<AstNode
*> new_children
;
1316 for (size_t i
= 0; i
< children
.size(); i
++)
1317 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
) {
1318 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1319 current_ast_mod
->children
.push_back(children
[i
]);
1320 current_scope
[children
[i
]->str
] = children
[i
];
1322 new_children
.push_back(children
[i
]);
1324 children
.swap(new_children
);
1325 did_something
= true;
1329 // simplify unconditional generate block
1330 if (type
== AST_GENBLOCK
&& children
.size() != 0)
1333 std::map
<std::string
, std::string
> name_map
;
1334 expand_genblock(std::string(), str
+ ".", name_map
);
1337 for (size_t i
= 0; i
< children
.size(); i
++) {
1338 children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1339 current_ast_mod
->children
.push_back(children
[i
]);
1343 did_something
= true;
1346 // simplify generate-if blocks
1347 if (type
== AST_GENIF
&& children
.size() != 0)
1349 AstNode
*buf
= children
[0]->clone();
1350 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1351 if (buf
->type
!= AST_CONSTANT
) {
1352 // for (auto f : log_files)
1353 // dumpAst(f, "verilog-ast> ");
1354 log_file_error(filename
, linenum
, "Condition for generate if is not constant!\n");
1356 if (buf
->asBool() != 0) {
1358 buf
= children
[1]->clone();
1361 buf
= children
.size() > 2 ? children
[2]->clone() : NULL
;
1366 if (buf
->type
!= AST_GENBLOCK
)
1367 buf
= new AstNode(AST_GENBLOCK
, buf
);
1369 if (!buf
->str
.empty()) {
1370 std::map
<std::string
, std::string
> name_map
;
1371 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1374 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1375 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1376 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1379 buf
->children
.clear();
1384 did_something
= true;
1387 // simplify generate-case blocks
1388 if (type
== AST_GENCASE
&& children
.size() != 0)
1390 AstNode
*buf
= children
[0]->clone();
1391 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1392 if (buf
->type
!= AST_CONSTANT
) {
1393 // for (auto f : log_files)
1394 // dumpAst(f, "verilog-ast> ");
1395 log_file_error(filename
, linenum
, "Condition for generate case is not constant!\n");
1398 bool ref_signed
= buf
->is_signed
;
1399 RTLIL::Const ref_value
= buf
->bitsAsConst();
1402 AstNode
*selected_case
= NULL
;
1403 for (size_t i
= 1; i
< children
.size(); i
++)
1405 log_assert(children
.at(i
)->type
== AST_COND
|| children
.at(i
)->type
== AST_CONDX
|| children
.at(i
)->type
== AST_CONDZ
);
1407 AstNode
*this_genblock
= NULL
;
1408 for (auto child
: children
.at(i
)->children
) {
1409 log_assert(this_genblock
== NULL
);
1410 if (child
->type
== AST_GENBLOCK
)
1411 this_genblock
= child
;
1414 for (auto child
: children
.at(i
)->children
)
1416 if (child
->type
== AST_DEFAULT
) {
1417 if (selected_case
== NULL
)
1418 selected_case
= this_genblock
;
1421 if (child
->type
== AST_GENBLOCK
)
1424 buf
= child
->clone();
1425 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
1426 if (buf
->type
!= AST_CONSTANT
) {
1427 // for (auto f : log_files)
1428 // dumpAst(f, "verilog-ast> ");
1429 log_file_error(filename
, linenum
, "Expression in generate case is not constant!\n");
1432 bool is_selected
= RTLIL::const_eq(ref_value
, buf
->bitsAsConst(), ref_signed
&& buf
->is_signed
, ref_signed
&& buf
->is_signed
, 1).as_bool();
1436 selected_case
= this_genblock
;
1437 i
= children
.size();
1443 if (selected_case
!= NULL
)
1445 log_assert(selected_case
->type
== AST_GENBLOCK
);
1446 buf
= selected_case
->clone();
1448 if (!buf
->str
.empty()) {
1449 std::map
<std::string
, std::string
> name_map
;
1450 buf
->expand_genblock(std::string(), buf
->str
+ ".", name_map
);
1453 for (size_t i
= 0; i
< buf
->children
.size(); i
++) {
1454 buf
->children
[i
]->simplify(false, false, false, stage
, -1, false, false);
1455 current_ast_mod
->children
.push_back(buf
->children
[i
]);
1458 buf
->children
.clear();
1463 did_something
= true;
1466 // unroll cell arrays
1467 if (type
== AST_CELLARRAY
)
1469 if (!children
.at(0)->range_valid
)
1470 log_file_error(filename
, linenum
, "Non-constant array range on cell array.\n");
1472 newNode
= new AstNode(AST_GENBLOCK
);
1473 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;
1475 for (int i
= 0; i
< num
; i
++) {
1476 int idx
= children
.at(0)->range_left
> children
.at(0)->range_right
? children
.at(0)->range_right
+ i
: children
.at(0)->range_right
- i
;
1477 AstNode
*new_cell
= children
.at(1)->clone();
1478 newNode
->children
.push_back(new_cell
);
1479 new_cell
->str
+= stringf("[%d]", idx
);
1480 if (new_cell
->type
== AST_PRIMITIVE
) {
1481 log_file_error(filename
, linenum
, "Cell arrays of primitives are currently not supported.\n");
1483 log_assert(new_cell
->children
.at(0)->type
== AST_CELLTYPE
);
1484 new_cell
->children
.at(0)->str
= stringf("$array:%d:%d:%s", i
, num
, new_cell
->children
.at(0)->str
.c_str());
1491 // replace primitives with assignments
1492 if (type
== AST_PRIMITIVE
)
1494 if (children
.size() < 2)
1495 log_file_error(filename
, linenum
, "Insufficient number of arguments for primitive `%s'!\n", str
.c_str());
1497 std::vector
<AstNode
*> children_list
;
1498 for (auto child
: children
) {
1499 log_assert(child
->type
== AST_ARGUMENT
);
1500 log_assert(child
->children
.size() == 1);
1501 children_list
.push_back(child
->children
[0]);
1502 child
->children
.clear();
1507 if (str
== "bufif0" || str
== "bufif1" || str
== "notif0" || str
== "notif1")
1509 if (children_list
.size() != 3)
1510 log_file_error(filename
, linenum
, "Invalid number of arguments for primitive `%s'!\n", str
.c_str());
1512 std::vector
<RTLIL::State
> z_const(1, RTLIL::State::Sz
);
1514 AstNode
*mux_input
= children_list
.at(1);
1515 if (str
== "notif0" || str
== "notif1") {
1516 mux_input
= new AstNode(AST_BIT_NOT
, mux_input
);
1518 AstNode
*node
= new AstNode(AST_TERNARY
, children_list
.at(2));
1519 if (str
== "bufif0") {
1520 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1521 node
->children
.push_back(mux_input
);
1523 node
->children
.push_back(mux_input
);
1524 node
->children
.push_back(AstNode::mkconst_bits(z_const
, false));
1529 children
.push_back(children_list
.at(0));
1530 children
.back()->was_checked
= true;
1531 children
.push_back(node
);
1532 did_something
= true;
1536 AstNodeType op_type
= AST_NONE
;
1537 bool invert_results
= false;
1540 op_type
= AST_BIT_AND
;
1542 op_type
= AST_BIT_AND
, invert_results
= true;
1544 op_type
= AST_BIT_OR
;
1546 op_type
= AST_BIT_OR
, invert_results
= true;
1548 op_type
= AST_BIT_XOR
;
1550 op_type
= AST_BIT_XOR
, invert_results
= true;
1554 op_type
= AST_POS
, invert_results
= true;
1555 log_assert(op_type
!= AST_NONE
);
1557 AstNode
*node
= children_list
[1];
1558 if (op_type
!= AST_POS
)
1559 for (size_t i
= 2; i
< children_list
.size(); i
++)
1560 node
= new AstNode(op_type
, node
, children_list
[i
]);
1562 node
= new AstNode(AST_BIT_NOT
, node
);
1566 children
.push_back(children_list
[0]);
1567 children
.back()->was_checked
= true;
1568 children
.push_back(node
);
1569 did_something
= true;
1573 // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
1574 // a big case block that selects the correct single-bit assignment.
1575 if (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) {
1576 if (children
[0]->type
!= AST_IDENTIFIER
|| children
[0]->children
.size() == 0)
1577 goto skip_dynamic_range_lvalue_expansion
;
1578 if (children
[0]->children
[0]->range_valid
|| did_something
)
1579 goto skip_dynamic_range_lvalue_expansion
;
1580 if (children
[0]->id2ast
== NULL
|| children
[0]->id2ast
->type
!= AST_WIRE
)
1581 goto skip_dynamic_range_lvalue_expansion
;
1582 if (!children
[0]->id2ast
->range_valid
)
1583 goto skip_dynamic_range_lvalue_expansion
;
1584 int source_width
= children
[0]->id2ast
->range_left
- children
[0]->id2ast
->range_right
+ 1;
1585 int result_width
= 1;
1586 AstNode
*shift_expr
= NULL
;
1587 AstNode
*range
= children
[0]->children
[0];
1588 if (range
->children
.size() == 1) {
1589 shift_expr
= range
->children
[0]->clone();
1591 shift_expr
= range
->children
[1]->clone();
1592 AstNode
*left_at_zero_ast
= range
->children
[0]->clone();
1593 AstNode
*right_at_zero_ast
= range
->children
[1]->clone();
1594 while (left_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1595 while (right_at_zero_ast
->simplify(true, true, false, stage
, -1, false, false)) { }
1596 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
1597 log_file_error(filename
, linenum
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
1598 result_width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
1600 did_something
= true;
1601 newNode
= new AstNode(AST_CASE
, shift_expr
);
1602 for (int i
= 0; i
<= source_width
-result_width
; i
++) {
1603 int start_bit
= children
[0]->id2ast
->range_right
+ i
;
1604 AstNode
*cond
= new AstNode(AST_COND
, mkconst_int(start_bit
, true));
1605 AstNode
*lvalue
= children
[0]->clone();
1606 lvalue
->delete_children();
1607 lvalue
->children
.push_back(new AstNode(AST_RANGE
,
1608 mkconst_int(start_bit
+result_width
-1, true), mkconst_int(start_bit
, true)));
1609 cond
->children
.push_back(new AstNode(AST_BLOCK
, new AstNode(type
, lvalue
, children
[1]->clone())));
1610 newNode
->children
.push_back(cond
);
1614 skip_dynamic_range_lvalue_expansion
:;
1616 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && current_block
!= NULL
)
1618 std::stringstream sstr
;
1619 sstr
<< "$formal$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1620 std::string id_check
= sstr
.str() + "_CHECK", id_en
= sstr
.str() + "_EN";
1622 AstNode
*wire_check
= new AstNode(AST_WIRE
);
1623 wire_check
->str
= id_check
;
1624 wire_check
->was_checked
= true;
1625 current_ast_mod
->children
.push_back(wire_check
);
1626 current_scope
[wire_check
->str
] = wire_check
;
1627 while (wire_check
->simplify(true, false, false, 1, -1, false, false)) { }
1629 AstNode
*wire_en
= new AstNode(AST_WIRE
);
1630 wire_en
->str
= id_en
;
1631 wire_en
->was_checked
= true;
1632 current_ast_mod
->children
.push_back(wire_en
);
1633 if (current_always_clocked
) {
1634 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)))));
1635 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->str
= id_en
;
1636 current_ast_mod
->children
.back()->children
[0]->children
[0]->children
[0]->was_checked
= true;
1638 current_scope
[wire_en
->str
] = wire_en
;
1639 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
1641 AstNode
*check_defval
;
1642 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
1643 check_defval
= new AstNode(AST_REDUCE_BOOL
, children
[0]->clone());
1645 std::vector
<RTLIL::State
> x_bit
;
1646 x_bit
.push_back(RTLIL::State::Sx
);
1647 check_defval
= mkconst_bits(x_bit
, false);
1650 AstNode
*assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), check_defval
);
1651 assign_check
->children
[0]->str
= id_check
;
1652 assign_check
->children
[0]->was_checked
= true;
1654 AstNode
*assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, 1));
1655 assign_en
->children
[0]->str
= id_en
;
1656 assign_en
->children
[0]->was_checked
= true;
1658 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
1659 default_signals
->children
.push_back(assign_check
);
1660 default_signals
->children
.push_back(assign_en
);
1661 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
1663 if (type
== AST_LIVE
|| type
== AST_FAIR
) {
1664 assign_check
= nullptr;
1666 assign_check
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_REDUCE_BOOL
, children
[0]->clone()));
1667 assign_check
->children
[0]->str
= id_check
;
1668 assign_check
->children
[0]->was_checked
= true;
1671 if (current_always
== nullptr || current_always
->type
!= AST_INITIAL
) {
1672 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(1, false, 1));
1674 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_FCALL
));
1675 assign_en
->children
[1]->str
= "\\$initstate";
1677 assign_en
->children
[0]->str
= id_en
;
1678 assign_en
->children
[0]->was_checked
= true;
1680 newNode
= new AstNode(AST_BLOCK
);
1681 if (assign_check
!= nullptr)
1682 newNode
->children
.push_back(assign_check
);
1683 newNode
->children
.push_back(assign_en
);
1685 AstNode
*assertnode
= new AstNode(type
);
1686 assertnode
->str
= str
;
1687 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1688 assertnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1689 assertnode
->children
[0]->str
= id_check
;
1690 assertnode
->children
[1]->str
= id_en
;
1691 assertnode
->attributes
.swap(attributes
);
1692 current_ast_mod
->children
.push_back(assertnode
);
1697 if (stage
> 1 && (type
== AST_ASSERT
|| type
== AST_ASSUME
|| type
== AST_LIVE
|| type
== AST_FAIR
|| type
== AST_COVER
) && children
.size() == 1)
1699 children
.push_back(mkconst_int(1, false, 1));
1700 did_something
= true;
1703 // found right-hand side identifier for memory -> replace with memory read port
1704 if (stage
> 1 && type
== AST_IDENTIFIER
&& id2ast
!= NULL
&& id2ast
->type
== AST_MEMORY
&& !in_lvalue
&&
1705 children
.size() == 1 && children
[0]->type
== AST_RANGE
&& children
[0]->children
.size() == 1) {
1706 newNode
= new AstNode(AST_MEMRD
, children
[0]->children
[0]->clone());
1708 newNode
->id2ast
= id2ast
;
1712 // assignment with nontrivial member in left-hand concat expression -> split assignment
1713 if ((type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_CONCAT
&& width_hint
> 0)
1715 bool found_nontrivial_member
= false;
1717 for (auto child
: children
[0]->children
) {
1718 if (child
->type
== AST_IDENTIFIER
&& child
->id2ast
!= NULL
&& child
->id2ast
->type
== AST_MEMORY
)
1719 found_nontrivial_member
= true;
1722 if (found_nontrivial_member
)
1724 newNode
= new AstNode(AST_BLOCK
);
1726 AstNode
*wire_tmp
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
1727 wire_tmp
->str
= stringf("$splitcmplxassign$%s:%d$%d", filename
.c_str(), linenum
, autoidx
++);
1728 current_ast_mod
->children
.push_back(wire_tmp
);
1729 current_scope
[wire_tmp
->str
] = wire_tmp
;
1730 wire_tmp
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
1731 while (wire_tmp
->simplify(true, false, false, 1, -1, false, false)) { }
1732 wire_tmp
->is_logic
= true;
1734 AstNode
*wire_tmp_id
= new AstNode(AST_IDENTIFIER
);
1735 wire_tmp_id
->str
= wire_tmp
->str
;
1737 newNode
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, wire_tmp_id
, children
[1]->clone()));
1738 newNode
->children
.back()->was_checked
= true;
1741 for (auto child
: children
[0]->children
)
1743 int child_width_hint
= -1;
1744 bool child_sign_hint
= true;
1745 child
->detectSignWidth(child_width_hint
, child_sign_hint
);
1747 AstNode
*rhs
= wire_tmp_id
->clone();
1748 rhs
->children
.push_back(new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
+child_width_hint
-1, true), AstNode::mkconst_int(cursor
, true)));
1749 newNode
->children
.push_back(new AstNode(type
, child
->clone(), rhs
));
1751 cursor
+= child_width_hint
;
1758 // assignment with memory in left-hand side expression -> replace with memory write port
1759 if (stage
> 1 && (type
== AST_ASSIGN_EQ
|| type
== AST_ASSIGN_LE
) && children
[0]->type
== AST_IDENTIFIER
&&
1760 children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
&& children
[0]->id2ast
->children
.size() >= 2 &&
1761 children
[0]->id2ast
->children
[0]->range_valid
&& children
[0]->id2ast
->children
[1]->range_valid
&&
1762 (children
[0]->children
.size() == 1 || children
[0]->children
.size() == 2) && children
[0]->children
[0]->type
== AST_RANGE
)
1764 std::stringstream sstr
;
1765 sstr
<< "$memwr$" << children
[0]->str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
1766 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA", id_en
= sstr
.str() + "_EN";
1768 int mem_width
, mem_size
, addr_bits
;
1769 bool mem_signed
= children
[0]->id2ast
->is_signed
;
1770 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
1772 int data_range_left
= children
[0]->id2ast
->children
[0]->range_left
;
1773 int data_range_right
= children
[0]->id2ast
->children
[0]->range_right
;
1774 int mem_data_range_offset
= std::min(data_range_left
, data_range_right
);
1776 int addr_width_hint
= -1;
1777 bool addr_sign_hint
= true;
1778 children
[0]->children
[0]->children
[0]->detectSignWidthWorker(addr_width_hint
, addr_sign_hint
);
1779 addr_bits
= std::max(addr_bits
, addr_width_hint
);
1781 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
1782 wire_addr
->str
= id_addr
;
1783 wire_addr
->was_checked
= true;
1784 current_ast_mod
->children
.push_back(wire_addr
);
1785 current_scope
[wire_addr
->str
] = wire_addr
;
1786 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
1788 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
1789 wire_data
->str
= id_data
;
1790 wire_data
->was_checked
= true;
1791 wire_data
->is_signed
= mem_signed
;
1792 current_ast_mod
->children
.push_back(wire_data
);
1793 current_scope
[wire_data
->str
] = wire_data
;
1794 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
1796 AstNode
*wire_en
= nullptr;
1797 if (current_always
->type
!= AST_INITIAL
) {
1798 wire_en
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
1799 wire_en
->str
= id_en
;
1800 wire_en
->was_checked
= true;
1801 current_ast_mod
->children
.push_back(wire_en
);
1802 current_scope
[wire_en
->str
] = wire_en
;
1803 while (wire_en
->simplify(true, false, false, 1, -1, false, false)) { }
1806 std::vector
<RTLIL::State
> x_bits_addr
, x_bits_data
, set_bits_en
;
1807 for (int i
= 0; i
< addr_bits
; i
++)
1808 x_bits_addr
.push_back(RTLIL::State::Sx
);
1809 for (int i
= 0; i
< mem_width
; i
++)
1810 x_bits_data
.push_back(RTLIL::State::Sx
);
1811 for (int i
= 0; i
< mem_width
; i
++)
1812 set_bits_en
.push_back(RTLIL::State::S1
);
1814 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_addr
, false));
1815 assign_addr
->children
[0]->str
= id_addr
;
1816 assign_addr
->children
[0]->was_checked
= true;
1818 AstNode
*assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(x_bits_data
, false));
1819 assign_data
->children
[0]->str
= id_data
;
1820 assign_data
->children
[0]->was_checked
= true;
1822 AstNode
*assign_en
= nullptr;
1823 if (current_always
->type
!= AST_INITIAL
) {
1824 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_int(0, false, mem_width
));
1825 assign_en
->children
[0]->str
= id_en
;
1826 assign_en
->children
[0]->was_checked
= true;
1829 AstNode
*default_signals
= new AstNode(AST_BLOCK
);
1830 default_signals
->children
.push_back(assign_addr
);
1831 default_signals
->children
.push_back(assign_data
);
1832 if (current_always
->type
!= AST_INITIAL
)
1833 default_signals
->children
.push_back(assign_en
);
1834 current_top_block
->children
.insert(current_top_block
->children
.begin(), default_signals
);
1836 assign_addr
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
1837 assign_addr
->children
[0]->str
= id_addr
;
1838 assign_addr
->children
[0]->was_checked
= true;
1840 if (children
[0]->children
.size() == 2)
1842 if (children
[0]->children
[1]->range_valid
)
1844 int offset
= children
[0]->children
[1]->range_right
;
1845 int width
= children
[0]->children
[1]->range_left
- offset
+ 1;
1846 offset
-= mem_data_range_offset
;
1848 std::vector
<RTLIL::State
> padding_x(offset
, RTLIL::State::Sx
);
1850 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1851 new AstNode(AST_CONCAT
, mkconst_bits(padding_x
, false), children
[1]->clone()));
1852 assign_data
->children
[0]->str
= id_data
;
1853 assign_data
->children
[0]->was_checked
= true;
1855 if (current_always
->type
!= AST_INITIAL
) {
1856 for (int i
= 0; i
< mem_width
; i
++)
1857 set_bits_en
[i
] = offset
<= i
&& i
< offset
+width
? RTLIL::State::S1
: RTLIL::State::S0
;
1858 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
1859 assign_en
->children
[0]->str
= id_en
;
1860 assign_en
->children
[0]->was_checked
= true;
1865 AstNode
*the_range
= children
[0]->children
[1];
1866 AstNode
*left_at_zero_ast
= the_range
->children
[0]->clone();
1867 AstNode
*right_at_zero_ast
= the_range
->children
.size() >= 2 ? the_range
->children
[1]->clone() : left_at_zero_ast
->clone();
1868 AstNode
*offset_ast
= right_at_zero_ast
->clone();
1870 if (mem_data_range_offset
)
1871 offset_ast
= new AstNode(AST_SUB
, offset_ast
, mkconst_int(mem_data_range_offset
, true));
1873 while (left_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
1874 while (right_at_zero_ast
->simplify(true, true, false, 1, -1, false, false)) { }
1875 if (left_at_zero_ast
->type
!= AST_CONSTANT
|| right_at_zero_ast
->type
!= AST_CONSTANT
)
1876 log_file_error(filename
, linenum
, "Unsupported expression on dynamic range select on signal `%s'!\n", str
.c_str());
1877 int width
= abs(int(left_at_zero_ast
->integer
- right_at_zero_ast
->integer
)) + 1;
1879 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1880 new AstNode(AST_SHIFT_LEFT
, children
[1]->clone(), offset_ast
->clone()));
1881 assign_data
->children
[0]->str
= id_data
;
1882 assign_data
->children
[0]->was_checked
= true;
1884 if (current_always
->type
!= AST_INITIAL
) {
1885 for (int i
= 0; i
< mem_width
; i
++)
1886 set_bits_en
[i
] = i
< width
? RTLIL::State::S1
: RTLIL::State::S0
;
1887 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
),
1888 new AstNode(AST_SHIFT_LEFT
, mkconst_bits(set_bits_en
, false), offset_ast
->clone()));
1889 assign_en
->children
[0]->str
= id_en
;
1890 assign_en
->children
[0]->was_checked
= true;
1893 delete left_at_zero_ast
;
1894 delete right_at_zero_ast
;
1900 assign_data
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), children
[1]->clone());
1901 assign_data
->children
[0]->str
= id_data
;
1902 assign_data
->children
[0]->was_checked
= true;
1904 if (current_always
->type
!= AST_INITIAL
) {
1905 assign_en
= new AstNode(AST_ASSIGN_LE
, new AstNode(AST_IDENTIFIER
), mkconst_bits(set_bits_en
, false));
1906 assign_en
->children
[0]->str
= id_en
;
1907 assign_en
->children
[0]->was_checked
= true;
1911 newNode
= new AstNode(AST_BLOCK
);
1912 newNode
->children
.push_back(assign_addr
);
1913 newNode
->children
.push_back(assign_data
);
1914 if (current_always
->type
!= AST_INITIAL
)
1915 newNode
->children
.push_back(assign_en
);
1917 AstNode
*wrnode
= new AstNode(current_always
->type
== AST_INITIAL
? AST_MEMINIT
: AST_MEMWR
);
1918 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1919 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1920 if (current_always
->type
!= AST_INITIAL
)
1921 wrnode
->children
.push_back(new AstNode(AST_IDENTIFIER
));
1923 wrnode
->children
.push_back(AstNode::mkconst_int(1, false));
1924 wrnode
->str
= children
[0]->str
;
1925 wrnode
->id2ast
= children
[0]->id2ast
;
1926 wrnode
->children
[0]->str
= id_addr
;
1927 wrnode
->children
[1]->str
= id_data
;
1928 if (current_always
->type
!= AST_INITIAL
)
1929 wrnode
->children
[2]->str
= id_en
;
1930 current_ast_mod
->children
.push_back(wrnode
);
1935 // replace function and task calls with the code from the function or task
1936 if ((type
== AST_FCALL
|| type
== AST_TCALL
) && !str
.empty())
1938 if (type
== AST_FCALL
)
1940 if (str
== "\\$initstate")
1942 int myidx
= autoidx
++;
1944 AstNode
*wire
= new AstNode(AST_WIRE
);
1945 wire
->str
= stringf("$initstate$%d_wire", myidx
);
1946 current_ast_mod
->children
.push_back(wire
);
1947 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
1949 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
), new AstNode(AST_ARGUMENT
, new AstNode(AST_IDENTIFIER
)));
1950 cell
->str
= stringf("$initstate$%d", myidx
);
1951 cell
->children
[0]->str
= "$initstate";
1952 cell
->children
[1]->str
= "\\Y";
1953 cell
->children
[1]->children
[0]->str
= wire
->str
;
1954 cell
->children
[1]->children
[0]->id2ast
= wire
;
1955 current_ast_mod
->children
.push_back(cell
);
1956 while (cell
->simplify(true, false, false, 1, -1, false, false)) { }
1958 newNode
= new AstNode(AST_IDENTIFIER
);
1959 newNode
->str
= wire
->str
;
1960 newNode
->id2ast
= wire
;
1964 if (str
== "\\$past")
1967 goto replace_fcall_later
;
1971 if (GetSize(children
) != 1 && GetSize(children
) != 2)
1972 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1 or 2.\n",
1973 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
1975 if (!current_always_clocked
)
1976 log_file_error(filename
, linenum
, "System function %s is only allowed in clocked blocks.\n",
1977 RTLIL::unescape_id(str
).c_str());
1979 if (GetSize(children
) == 2)
1981 AstNode
*buf
= children
[1]->clone();
1982 while (buf
->simplify(true, false, false, stage
, -1, false, false)) { }
1983 if (buf
->type
!= AST_CONSTANT
)
1984 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
1986 num_steps
= buf
->asInt(true);
1990 AstNode
*block
= nullptr;
1992 for (auto child
: current_always
->children
)
1993 if (child
->type
== AST_BLOCK
)
1996 log_assert(block
!= nullptr);
1998 if (num_steps
== 0) {
1999 newNode
= children
[0]->clone();
2003 int myidx
= autoidx
++;
2004 AstNode
*outreg
= nullptr;
2006 for (int i
= 0; i
< num_steps
; i
++)
2008 AstNode
*reg
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
,
2009 mkconst_int(width_hint
-1, true), mkconst_int(0, true)));
2011 reg
->str
= stringf("$past$%s:%d$%d$%d", filename
.c_str(), linenum
, myidx
, i
);
2014 current_ast_mod
->children
.push_back(reg
);
2016 while (reg
->simplify(true, false, false, 1, -1, false, false)) { }
2018 AstNode
*regid
= new AstNode(AST_IDENTIFIER
);
2019 regid
->str
= reg
->str
;
2020 regid
->id2ast
= reg
;
2021 regid
->was_checked
= true;
2023 AstNode
*rhs
= nullptr;
2025 if (outreg
== nullptr) {
2026 rhs
= children
.at(0)->clone();
2028 rhs
= new AstNode(AST_IDENTIFIER
);
2029 rhs
->str
= outreg
->str
;
2030 rhs
->id2ast
= outreg
;
2033 block
->children
.push_back(new AstNode(AST_ASSIGN_LE
, regid
, rhs
));
2037 newNode
= new AstNode(AST_IDENTIFIER
);
2038 newNode
->str
= outreg
->str
;
2039 newNode
->id2ast
= outreg
;
2043 if (str
== "\\$stable" || str
== "\\$rose" || str
== "\\$fell" || str
== "\\$changed")
2045 if (GetSize(children
) != 1)
2046 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1.\n",
2047 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2049 if (!current_always_clocked
)
2050 log_file_error(filename
, linenum
, "System function %s is only allowed in clocked blocks.\n",
2051 RTLIL::unescape_id(str
).c_str());
2053 AstNode
*present
= children
.at(0)->clone();
2054 AstNode
*past
= clone();
2055 past
->str
= "\\$past";
2057 if (str
== "\\$stable")
2058 newNode
= new AstNode(AST_EQ
, past
, present
);
2060 else if (str
== "\\$changed")
2061 newNode
= new AstNode(AST_NE
, past
, present
);
2063 else if (str
== "\\$rose")
2064 newNode
= new AstNode(AST_LOGIC_AND
,
2065 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false))),
2066 new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false)));
2068 else if (str
== "\\$fell")
2069 newNode
= new AstNode(AST_LOGIC_AND
,
2070 new AstNode(AST_BIT_AND
, past
, mkconst_int(1,false)),
2071 new AstNode(AST_LOGIC_NOT
, new AstNode(AST_BIT_AND
, present
, mkconst_int(1,false))));
2079 // $anyconst and $anyseq are mapped in AstNode::genRTLIL()
2080 if (str
== "\\$anyconst" || str
== "\\$anyseq" || str
== "\\$allconst" || str
== "\\$allseq") {
2081 recursion_counter
--;
2085 if (str
== "\\$clog2")
2087 if (children
.size() != 1)
2088 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1.\n",
2089 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2091 AstNode
*buf
= children
[0]->clone();
2092 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2093 if (buf
->type
!= AST_CONSTANT
)
2094 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant value.\n", str
.c_str());
2096 RTLIL::Const arg_value
= buf
->bitsAsConst();
2097 if (arg_value
.as_bool())
2098 arg_value
= const_sub(arg_value
, 1, false, false, GetSize(arg_value
));
2101 uint32_t result
= 0;
2102 for (size_t i
= 0; i
< arg_value
.bits
.size(); i
++)
2103 if (arg_value
.bits
.at(i
) == RTLIL::State::S1
)
2106 newNode
= mkconst_int(result
, true);
2110 if (str
== "\\$size" || str
== "\\$bits")
2112 if (str
== "\\$bits" && children
.size() != 1)
2113 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1.\n",
2114 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2116 if (str
== "\\$size" && children
.size() != 1 && children
.size() != 2)
2117 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1 or 2.\n",
2118 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2121 if (str
== "\\$size" && children
.size() == 2) {
2122 AstNode
*buf
= children
[1]->clone();
2123 // Evaluate constant expression
2124 while (buf
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2125 dim
= buf
->asInt(false);
2128 AstNode
*buf
= children
[0]->clone();
2130 AstNode
*id_ast
= NULL
;
2133 //while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
2134 buf
->detectSignWidth(width_hint
, sign_hint
);
2136 if (buf
->type
== AST_IDENTIFIER
) {
2137 id_ast
= buf
->id2ast
;
2138 if (id_ast
== NULL
&& current_scope
.count(buf
->str
))
2139 id_ast
= current_scope
.at(buf
->str
);
2141 log_file_error(filename
, linenum
, "Failed to resolve identifier %s for width detection!\n", buf
->str
.c_str());
2142 if (id_ast
->type
== AST_MEMORY
) {
2143 // We got here only if the argument is a memory
2144 // Otherwise $size() and $bits() return the expression width
2145 AstNode
*mem_range
= id_ast
->children
[1];
2146 if (str
== "\\$bits") {
2147 if (mem_range
->type
== AST_RANGE
) {
2148 if (!mem_range
->range_valid
)
2149 log_file_error(filename
, linenum
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2150 mem_depth
= mem_range
->range_left
- mem_range
->range_right
+ 1;
2152 log_file_error(filename
, linenum
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2155 if (mem_range
->type
== AST_RANGE
) {
2156 if (!mem_range
->range_valid
)
2157 log_file_error(filename
, linenum
, "Failed to detect width of memory access `%s'!\n", buf
->str
.c_str());
2159 if (id_ast
->multirange_dimensions
.empty())
2162 dims
= GetSize(id_ast
->multirange_dimensions
)/2;
2164 width_hint
= (dims
> 1) ? id_ast
->multirange_dimensions
[1] : (mem_range
->range_left
- mem_range
->range_right
+ 1);
2165 else if (dim
<= dims
) {
2166 width_hint
= id_ast
->multirange_dimensions
[2*dim
-1];
2167 } else if ((dim
> dims
+1) || (dim
< 0))
2168 log_file_error(filename
, linenum
, "Dimension %d out of range in `%s', as it only has dimensions 1..%d!\n", dim
, buf
->str
.c_str(), dims
+1);
2170 log_file_error(filename
, linenum
, "Unknown memory depth AST type in `%s'!\n", buf
->str
.c_str());
2176 newNode
= mkconst_int(width_hint
* mem_depth
, false);
2180 if (str
== "\\$ln" || str
== "\\$log10" || str
== "\\$exp" || str
== "\\$sqrt" || str
== "\\$pow" ||
2181 str
== "\\$floor" || str
== "\\$ceil" || str
== "\\$sin" || str
== "\\$cos" || str
== "\\$tan" ||
2182 str
== "\\$asin" || str
== "\\$acos" || str
== "\\$atan" || str
== "\\$atan2" || str
== "\\$hypot" ||
2183 str
== "\\$sinh" || str
== "\\$cosh" || str
== "\\$tanh" || str
== "\\$asinh" || str
== "\\$acosh" || str
== "\\$atanh" ||
2184 str
== "\\$rtoi" || str
== "\\$itor")
2186 bool func_with_two_arguments
= str
== "\\$pow" || str
== "\\$atan2" || str
== "\\$hypot";
2187 double x
= 0, y
= 0;
2189 if (func_with_two_arguments
) {
2190 if (children
.size() != 2)
2191 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 2.\n",
2192 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2194 if (children
.size() != 1)
2195 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 1.\n",
2196 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2199 if (children
.size() >= 1) {
2200 while (children
[0]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2201 if (!children
[0]->isConst())
2202 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant argument.\n",
2203 RTLIL::unescape_id(str
).c_str());
2204 int child_width_hint
= width_hint
;
2205 bool child_sign_hint
= sign_hint
;
2206 children
[0]->detectSignWidth(child_width_hint
, child_sign_hint
);
2207 x
= children
[0]->asReal(child_sign_hint
);
2210 if (children
.size() >= 2) {
2211 while (children
[1]->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2212 if (!children
[1]->isConst())
2213 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant argument.\n",
2214 RTLIL::unescape_id(str
).c_str());
2215 int child_width_hint
= width_hint
;
2216 bool child_sign_hint
= sign_hint
;
2217 children
[1]->detectSignWidth(child_width_hint
, child_sign_hint
);
2218 y
= children
[1]->asReal(child_sign_hint
);
2221 if (str
== "\\$rtoi") {
2222 newNode
= AstNode::mkconst_int(x
, true);
2224 newNode
= new AstNode(AST_REALVALUE
);
2225 if (str
== "\\$ln") newNode
->realvalue
= ::log(x
);
2226 else if (str
== "\\$log10") newNode
->realvalue
= ::log10(x
);
2227 else if (str
== "\\$exp") newNode
->realvalue
= ::exp(x
);
2228 else if (str
== "\\$sqrt") newNode
->realvalue
= ::sqrt(x
);
2229 else if (str
== "\\$pow") newNode
->realvalue
= ::pow(x
, y
);
2230 else if (str
== "\\$floor") newNode
->realvalue
= ::floor(x
);
2231 else if (str
== "\\$ceil") newNode
->realvalue
= ::ceil(x
);
2232 else if (str
== "\\$sin") newNode
->realvalue
= ::sin(x
);
2233 else if (str
== "\\$cos") newNode
->realvalue
= ::cos(x
);
2234 else if (str
== "\\$tan") newNode
->realvalue
= ::tan(x
);
2235 else if (str
== "\\$asin") newNode
->realvalue
= ::asin(x
);
2236 else if (str
== "\\$acos") newNode
->realvalue
= ::acos(x
);
2237 else if (str
== "\\$atan") newNode
->realvalue
= ::atan(x
);
2238 else if (str
== "\\$atan2") newNode
->realvalue
= ::atan2(x
, y
);
2239 else if (str
== "\\$hypot") newNode
->realvalue
= ::hypot(x
, y
);
2240 else if (str
== "\\$sinh") newNode
->realvalue
= ::sinh(x
);
2241 else if (str
== "\\$cosh") newNode
->realvalue
= ::cosh(x
);
2242 else if (str
== "\\$tanh") newNode
->realvalue
= ::tanh(x
);
2243 else if (str
== "\\$asinh") newNode
->realvalue
= ::asinh(x
);
2244 else if (str
== "\\$acosh") newNode
->realvalue
= ::acosh(x
);
2245 else if (str
== "\\$atanh") newNode
->realvalue
= ::atanh(x
);
2246 else if (str
== "\\$itor") newNode
->realvalue
= x
;
2252 if (str
== "\\$sformatf") {
2253 AstNode
*node_string
= children
[0];
2254 while (node_string
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2255 if (node_string
->type
!= AST_CONSTANT
)
2256 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
2257 std::string sformat
= node_string
->bitsAsConst().decode_string();
2258 std::string sout
= process_format_str(sformat
, 1, stage
, width_hint
, sign_hint
);
2259 newNode
= AstNode::mkconst_str(sout
);
2263 if (current_scope
.count(str
) != 0 && current_scope
[str
]->type
== AST_DPI_FUNCTION
)
2265 AstNode
*dpi_decl
= current_scope
[str
];
2267 std::string rtype
, fname
;
2268 std::vector
<std::string
> argtypes
;
2269 std::vector
<AstNode
*> args
;
2271 rtype
= RTLIL::unescape_id(dpi_decl
->children
.at(0)->str
);
2272 fname
= RTLIL::unescape_id(dpi_decl
->children
.at(1)->str
);
2274 for (int i
= 2; i
< GetSize(dpi_decl
->children
); i
++)
2276 if (i
-2 >= GetSize(children
))
2277 log_file_error(filename
, linenum
, "Insufficient number of arguments in DPI function call.\n");
2279 argtypes
.push_back(RTLIL::unescape_id(dpi_decl
->children
.at(i
)->str
));
2280 args
.push_back(children
.at(i
-2)->clone());
2281 while (args
.back()->simplify(true, false, false, stage
, -1, false, true)) { }
2283 if (args
.back()->type
!= AST_CONSTANT
&& args
.back()->type
!= AST_REALVALUE
)
2284 log_file_error(filename
, linenum
, "Failed to evaluate DPI function with non-constant argument.\n");
2287 newNode
= dpi_call(rtype
, fname
, argtypes
, args
);
2289 for (auto arg
: args
)
2295 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_FUNCTION
)
2296 log_file_error(filename
, linenum
, "Can't resolve function name `%s'.\n", str
.c_str());
2299 if (type
== AST_TCALL
)
2301 if (str
== "$finish" || str
== "$stop")
2303 if (!current_always
|| current_always
->type
!= AST_INITIAL
)
2304 log_file_error(filename
, linenum
, "System task `%s' outside initial block is unsupported.\n", str
.c_str());
2306 log_file_error(filename
, linenum
, "System task `%s' executed.\n", str
.c_str());
2309 if (str
== "\\$readmemh" || str
== "\\$readmemb")
2311 if (GetSize(children
) < 2 || GetSize(children
) > 4)
2312 log_file_error(filename
, linenum
, "System function %s got %d arguments, expected 2-4.\n",
2313 RTLIL::unescape_id(str
).c_str(), int(children
.size()));
2315 AstNode
*node_filename
= children
[0]->clone();
2316 while (node_filename
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2317 if (node_filename
->type
!= AST_CONSTANT
)
2318 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str
.c_str());
2320 AstNode
*node_memory
= children
[1]->clone();
2321 while (node_memory
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2322 if (node_memory
->type
!= AST_IDENTIFIER
|| node_memory
->id2ast
== nullptr || node_memory
->id2ast
->type
!= AST_MEMORY
)
2323 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str
.c_str());
2325 int start_addr
= -1, finish_addr
= -1;
2327 if (GetSize(children
) > 2) {
2328 AstNode
*node_addr
= children
[2]->clone();
2329 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2330 if (node_addr
->type
!= AST_CONSTANT
)
2331 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str
.c_str());
2332 start_addr
= int(node_addr
->asInt(false));
2335 if (GetSize(children
) > 3) {
2336 AstNode
*node_addr
= children
[3]->clone();
2337 while (node_addr
->simplify(true, false, false, stage
, width_hint
, sign_hint
, false)) { }
2338 if (node_addr
->type
!= AST_CONSTANT
)
2339 log_file_error(filename
, linenum
, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str
.c_str());
2340 finish_addr
= int(node_addr
->asInt(false));
2343 bool unconditional_init
= false;
2344 if (current_always
->type
== AST_INITIAL
) {
2345 pool
<AstNode
*> queue
;
2346 log_assert(current_always
->children
[0]->type
== AST_BLOCK
);
2347 queue
.insert(current_always
->children
[0]);
2348 while (!unconditional_init
&& !queue
.empty()) {
2349 pool
<AstNode
*> next_queue
;
2350 for (auto n
: queue
)
2351 for (auto c
: n
->children
) {
2353 unconditional_init
= true;
2354 next_queue
.insert(c
);
2356 next_queue
.swap(queue
);
2360 newNode
= readmem(str
== "\\$readmemh", node_filename
->bitsAsConst().decode_string(), node_memory
->id2ast
, start_addr
, finish_addr
, unconditional_init
);
2361 delete node_filename
;
2366 if (current_scope
.count(str
) == 0 || current_scope
[str
]->type
!= AST_TASK
)
2367 log_file_error(filename
, linenum
, "Can't resolve task name `%s'.\n", str
.c_str());
2370 AstNode
*decl
= current_scope
[str
];
2372 std::stringstream sstr
;
2373 sstr
<< "$func$" << str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++) << "$";
2374 std::string prefix
= sstr
.str();
2376 bool recommend_const_eval
= false;
2377 bool require_const_eval
= in_param
? false : has_const_only_constructs(recommend_const_eval
);
2378 if ((in_param
|| recommend_const_eval
|| require_const_eval
) && !decl
->attributes
.count("\\via_celltype"))
2380 bool all_args_const
= true;
2381 for (auto child
: children
) {
2382 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
2383 if (child
->type
!= AST_CONSTANT
)
2384 all_args_const
= false;
2387 if (all_args_const
) {
2388 AstNode
*func_workspace
= current_scope
[str
]->clone();
2389 newNode
= func_workspace
->eval_const_function(this);
2390 delete func_workspace
;
2395 log_file_error(filename
, linenum
, "Non-constant function call in constant expression.\n");
2396 if (require_const_eval
)
2397 log_file_error(filename
, linenum
, "Function %s can only be called with constant arguments.\n", str
.c_str());
2400 size_t arg_count
= 0;
2401 std::map
<std::string
, std::string
> replace_rules
;
2402 vector
<AstNode
*> added_mod_children
;
2403 dict
<std::string
, AstNode
*> wire_cache
;
2404 vector
<AstNode
*> new_stmts
;
2405 vector
<AstNode
*> output_assignments
;
2407 if (current_block
== NULL
)
2409 log_assert(type
== AST_FCALL
);
2411 AstNode
*wire
= NULL
;
2412 for (auto child
: decl
->children
)
2413 if (child
->type
== AST_WIRE
&& child
->str
== str
)
2414 wire
= child
->clone();
2415 log_assert(wire
!= NULL
);
2417 wire
->str
= prefix
+ str
;
2419 wire
->is_input
= false;
2420 wire
->is_output
= false;
2422 current_ast_mod
->children
.push_back(wire
);
2423 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2425 AstNode
*lvalue
= new AstNode(AST_IDENTIFIER
);
2426 lvalue
->str
= wire
->str
;
2428 AstNode
*always
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
,
2429 new AstNode(AST_ASSIGN_EQ
, lvalue
, clone())));
2430 always
->children
[0]->children
[0]->was_checked
= true;
2432 current_ast_mod
->children
.push_back(always
);
2434 goto replace_fcall_with_id
;
2437 if (decl
->attributes
.count("\\via_celltype"))
2439 std::string celltype
= decl
->attributes
.at("\\via_celltype")->asAttrConst().decode_string();
2440 std::string outport
= str
;
2442 if (celltype
.find(' ') != std::string::npos
) {
2443 int pos
= celltype
.find(' ');
2444 outport
= RTLIL::escape_id(celltype
.substr(pos
+1));
2445 celltype
= RTLIL::escape_id(celltype
.substr(0, pos
));
2447 celltype
= RTLIL::escape_id(celltype
);
2449 AstNode
*cell
= new AstNode(AST_CELL
, new AstNode(AST_CELLTYPE
));
2450 cell
->str
= prefix
.substr(0, GetSize(prefix
)-1);
2451 cell
->children
[0]->str
= celltype
;
2453 for (auto attr
: decl
->attributes
)
2454 if (attr
.first
.str().rfind("\\via_celltype_defparam_", 0) == 0)
2456 AstNode
*cell_arg
= new AstNode(AST_PARASET
, attr
.second
->clone());
2457 cell_arg
->str
= RTLIL::escape_id(attr
.first
.substr(strlen("\\via_celltype_defparam_")));
2458 cell
->children
.push_back(cell_arg
);
2461 for (auto child
: decl
->children
)
2462 if (child
->type
== AST_WIRE
&& (child
->is_input
|| child
->is_output
|| (type
== AST_FCALL
&& child
->str
== str
)))
2464 AstNode
*wire
= child
->clone();
2465 wire
->str
= prefix
+ wire
->str
;
2467 wire
->is_input
= false;
2468 wire
->is_output
= false;
2469 current_ast_mod
->children
.push_back(wire
);
2470 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2472 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
2473 wire_id
->str
= wire
->str
;
2475 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
2477 AstNode
*arg
= children
[arg_count
++]->clone();
2478 AstNode
*assign
= child
->is_input
?
2479 new AstNode(AST_ASSIGN_EQ
, wire_id
->clone(), arg
) :
2480 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
->clone());
2481 assign
->children
[0]->was_checked
= true;
2483 for (auto it
= current_block
->children
.begin(); it
!= current_block
->children
.end(); it
++) {
2484 if (*it
!= current_block_child
)
2486 current_block
->children
.insert(it
, assign
);
2491 AstNode
*cell_arg
= new AstNode(AST_ARGUMENT
, wire_id
);
2492 cell_arg
->str
= child
->str
== str
? outport
: child
->str
;
2493 cell
->children
.push_back(cell_arg
);
2496 current_ast_mod
->children
.push_back(cell
);
2497 goto replace_fcall_with_id
;
2500 for (auto child
: decl
->children
)
2501 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
)
2503 AstNode
*wire
= nullptr;
2505 if (wire_cache
.count(child
->str
))
2507 wire
= wire_cache
.at(child
->str
);
2508 if (wire
->children
.empty()) {
2509 for (auto c
: child
->children
)
2510 wire
->children
.push_back(c
->clone());
2511 } else if (!child
->children
.empty()) {
2512 while (child
->simplify(true, false, false, stage
, -1, false, false)) { }
2513 if (GetSize(child
->children
) == GetSize(wire
->children
)) {
2514 for (int i
= 0; i
< GetSize(child
->children
); i
++)
2515 if (*child
->children
.at(i
) != *wire
->children
.at(i
))
2516 goto tcall_incompatible_wires
;
2518 tcall_incompatible_wires
:
2519 log_file_error(filename
, linenum
, "Incompatible re-declaration of wire %s.\n", child
->str
.c_str());
2525 wire
= child
->clone();
2526 wire
->str
= prefix
+ wire
->str
;
2528 wire
->is_input
= false;
2529 wire
->is_output
= false;
2530 wire
->is_reg
= true;
2531 wire
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
2532 wire_cache
[child
->str
] = wire
;
2534 current_ast_mod
->children
.push_back(wire
);
2535 added_mod_children
.push_back(wire
);
2538 if (child
->type
== AST_WIRE
)
2539 while (wire
->simplify(true, false, false, 1, -1, false, false)) { }
2541 replace_rules
[child
->str
] = wire
->str
;
2542 current_scope
[wire
->str
] = wire
;
2544 if ((child
->is_input
|| child
->is_output
) && arg_count
< children
.size())
2546 AstNode
*arg
= children
[arg_count
++]->clone();
2547 AstNode
*wire_id
= new AstNode(AST_IDENTIFIER
);
2548 wire_id
->str
= wire
->str
;
2549 AstNode
*assign
= child
->is_input
?
2550 new AstNode(AST_ASSIGN_EQ
, wire_id
, arg
) :
2551 new AstNode(AST_ASSIGN_EQ
, arg
, wire_id
);
2552 assign
->children
[0]->was_checked
= true;
2553 if (child
->is_input
)
2554 new_stmts
.push_back(assign
);
2556 output_assignments
.push_back(assign
);
2560 for (auto child
: added_mod_children
) {
2561 child
->replace_ids(prefix
, replace_rules
);
2562 while (child
->simplify(true, false, false, 1, -1, false, false)) { }
2565 for (auto child
: decl
->children
)
2566 if (child
->type
!= AST_WIRE
&& child
->type
!= AST_MEMORY
&& child
->type
!= AST_PARAMETER
&& child
->type
!= AST_LOCALPARAM
)
2568 AstNode
*stmt
= child
->clone();
2569 stmt
->replace_ids(prefix
, replace_rules
);
2570 new_stmts
.push_back(stmt
);
2573 new_stmts
.insert(new_stmts
.end(), output_assignments
.begin(), output_assignments
.end());
2575 for (auto it
= current_block
->children
.begin(); ; it
++) {
2576 log_assert(it
!= current_block
->children
.end());
2577 if (*it
== current_block_child
) {
2578 current_block
->children
.insert(it
, new_stmts
.begin(), new_stmts
.end());
2583 replace_fcall_with_id
:
2584 if (type
== AST_FCALL
) {
2586 type
= AST_IDENTIFIER
;
2589 if (type
== AST_TCALL
)
2591 did_something
= true;
2594 replace_fcall_later
:;
2596 // perform const folding when activated
2600 std::vector
<RTLIL::State
> tmp_bits
;
2601 RTLIL::Const (*const_func
)(const RTLIL::Const
&, const RTLIL::Const
&, bool, bool, int);
2602 RTLIL::Const dummy_arg
;
2606 case AST_IDENTIFIER
:
2607 if (current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_PARAMETER
|| current_scope
[str
]->type
== AST_LOCALPARAM
)) {
2608 if (current_scope
[str
]->children
[0]->type
== AST_CONSTANT
) {
2609 if (children
.size() != 0 && children
[0]->type
== AST_RANGE
&& children
[0]->range_valid
) {
2610 std::vector
<RTLIL::State
> data
;
2611 bool param_upto
= current_scope
[str
]->range_valid
&& current_scope
[str
]->range_swapped
;
2612 int param_offset
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_right
: 0;
2613 int param_width
= current_scope
[str
]->range_valid
? current_scope
[str
]->range_left
- current_scope
[str
]->range_right
+ 1 :
2614 GetSize(current_scope
[str
]->children
[0]->bits
);
2615 int tmp_range_left
= children
[0]->range_left
, tmp_range_right
= children
[0]->range_right
;
2617 tmp_range_left
= (param_width
+ 2*param_offset
) - children
[0]->range_right
- 1;
2618 tmp_range_right
= (param_width
+ 2*param_offset
) - children
[0]->range_left
- 1;
2620 for (int i
= tmp_range_right
; i
<= tmp_range_left
; i
++) {
2621 int index
= i
- param_offset
;
2622 if (0 <= index
&& index
< param_width
)
2623 data
.push_back(current_scope
[str
]->children
[0]->bits
[index
]);
2625 data
.push_back(RTLIL::State::Sx
);
2627 newNode
= mkconst_bits(data
, false);
2629 if (children
.size() == 0)
2630 newNode
= current_scope
[str
]->children
[0]->clone();
2632 if (current_scope
[str
]->children
[0]->isConst())
2633 newNode
= current_scope
[str
]->children
[0]->clone();
2635 else if (at_zero
&& current_scope
.count(str
) > 0 && (current_scope
[str
]->type
== AST_WIRE
|| current_scope
[str
]->type
== AST_AUTOWIRE
)) {
2636 newNode
= mkconst_int(0, sign_hint
, width_hint
);
2640 if (children
[0]->type
== AST_CONSTANT
) {
2641 RTLIL::Const y
= RTLIL::const_not(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
2642 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2646 case AST_TO_UNSIGNED
:
2647 if (children
[0]->type
== AST_CONSTANT
) {
2648 RTLIL::Const y
= children
[0]->bitsAsConst(width_hint
, sign_hint
);
2649 newNode
= mkconst_bits(y
.bits
, type
== AST_TO_SIGNED
);
2652 if (0) { case AST_BIT_AND
: const_func
= RTLIL::const_and
; }
2653 if (0) { case AST_BIT_OR
: const_func
= RTLIL::const_or
; }
2654 if (0) { case AST_BIT_XOR
: const_func
= RTLIL::const_xor
; }
2655 if (0) { case AST_BIT_XNOR
: const_func
= RTLIL::const_xnor
; }
2656 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2657 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
2658 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
2659 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2662 if (0) { case AST_REDUCE_AND
: const_func
= RTLIL::const_reduce_and
; }
2663 if (0) { case AST_REDUCE_OR
: const_func
= RTLIL::const_reduce_or
; }
2664 if (0) { case AST_REDUCE_XOR
: const_func
= RTLIL::const_reduce_xor
; }
2665 if (0) { case AST_REDUCE_XNOR
: const_func
= RTLIL::const_reduce_xnor
; }
2666 if (0) { case AST_REDUCE_BOOL
: const_func
= RTLIL::const_reduce_bool
; }
2667 if (children
[0]->type
== AST_CONSTANT
) {
2668 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), dummy_arg
, false, false, -1);
2669 newNode
= mkconst_bits(y
.bits
, false);
2673 if (children
[0]->type
== AST_CONSTANT
) {
2674 RTLIL::Const y
= RTLIL::const_logic_not(RTLIL::Const(children
[0]->bits
), dummy_arg
, children
[0]->is_signed
, false, -1);
2675 newNode
= mkconst_bits(y
.bits
, false);
2677 if (children
[0]->isConst()) {
2678 newNode
= mkconst_int(children
[0]->asReal(sign_hint
) == 0, false, 1);
2681 if (0) { case AST_LOGIC_AND
: const_func
= RTLIL::const_logic_and
; }
2682 if (0) { case AST_LOGIC_OR
: const_func
= RTLIL::const_logic_or
; }
2683 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2684 RTLIL::Const y
= const_func(RTLIL::Const(children
[0]->bits
), RTLIL::Const(children
[1]->bits
),
2685 children
[0]->is_signed
, children
[1]->is_signed
, -1);
2686 newNode
= mkconst_bits(y
.bits
, false);
2688 if (children
[0]->isConst() && children
[1]->isConst()) {
2689 if (type
== AST_LOGIC_AND
)
2690 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) && (children
[1]->asReal(sign_hint
) != 0), false, 1);
2692 newNode
= mkconst_int((children
[0]->asReal(sign_hint
) != 0) || (children
[1]->asReal(sign_hint
) != 0), false, 1);
2695 if (0) { case AST_SHIFT_LEFT
: const_func
= RTLIL::const_shl
; }
2696 if (0) { case AST_SHIFT_RIGHT
: const_func
= RTLIL::const_shr
; }
2697 if (0) { case AST_SHIFT_SLEFT
: const_func
= RTLIL::const_sshl
; }
2698 if (0) { case AST_SHIFT_SRIGHT
: const_func
= RTLIL::const_sshr
; }
2699 if (0) { case AST_POW
: const_func
= RTLIL::const_pow
; }
2700 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2701 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
2702 RTLIL::Const(children
[1]->bits
), sign_hint
, type
== AST_POW
? children
[1]->is_signed
: false, width_hint
);
2703 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2705 if (type
== AST_POW
&& children
[0]->isConst() && children
[1]->isConst()) {
2706 newNode
= new AstNode(AST_REALVALUE
);
2707 newNode
->realvalue
= pow(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
));
2710 if (0) { case AST_LT
: const_func
= RTLIL::const_lt
; }
2711 if (0) { case AST_LE
: const_func
= RTLIL::const_le
; }
2712 if (0) { case AST_EQ
: const_func
= RTLIL::const_eq
; }
2713 if (0) { case AST_NE
: const_func
= RTLIL::const_ne
; }
2714 if (0) { case AST_EQX
: const_func
= RTLIL::const_eqx
; }
2715 if (0) { case AST_NEX
: const_func
= RTLIL::const_nex
; }
2716 if (0) { case AST_GE
: const_func
= RTLIL::const_ge
; }
2717 if (0) { case AST_GT
: const_func
= RTLIL::const_gt
; }
2718 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2719 int cmp_width
= max(children
[0]->bits
.size(), children
[1]->bits
.size());
2720 bool cmp_signed
= children
[0]->is_signed
&& children
[1]->is_signed
;
2721 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(cmp_width
, cmp_signed
),
2722 children
[1]->bitsAsConst(cmp_width
, cmp_signed
), cmp_signed
, cmp_signed
, 1);
2723 newNode
= mkconst_bits(y
.bits
, false);
2725 if (children
[0]->isConst() && children
[1]->isConst()) {
2726 bool cmp_signed
= (children
[0]->type
== AST_REALVALUE
|| children
[0]->is_signed
) && (children
[1]->type
== AST_REALVALUE
|| children
[1]->is_signed
);
2728 case AST_LT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) < children
[1]->asReal(cmp_signed
), false, 1); break;
2729 case AST_LE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) <= children
[1]->asReal(cmp_signed
), false, 1); break;
2730 case AST_EQ
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
2731 case AST_NE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
2732 case AST_EQX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) == children
[1]->asReal(cmp_signed
), false, 1); break;
2733 case AST_NEX
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) != children
[1]->asReal(cmp_signed
), false, 1); break;
2734 case AST_GE
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) >= children
[1]->asReal(cmp_signed
), false, 1); break;
2735 case AST_GT
: newNode
= mkconst_int(children
[0]->asReal(cmp_signed
) > children
[1]->asReal(cmp_signed
), false, 1); break;
2736 default: log_abort();
2740 if (0) { case AST_ADD
: const_func
= RTLIL::const_add
; }
2741 if (0) { case AST_SUB
: const_func
= RTLIL::const_sub
; }
2742 if (0) { case AST_MUL
: const_func
= RTLIL::const_mul
; }
2743 if (0) { case AST_DIV
: const_func
= RTLIL::const_div
; }
2744 if (0) { case AST_MOD
: const_func
= RTLIL::const_mod
; }
2745 if (children
[0]->type
== AST_CONSTANT
&& children
[1]->type
== AST_CONSTANT
) {
2746 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
),
2747 children
[1]->bitsAsConst(width_hint
, sign_hint
), sign_hint
, sign_hint
, width_hint
);
2748 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2750 if (children
[0]->isConst() && children
[1]->isConst()) {
2751 newNode
= new AstNode(AST_REALVALUE
);
2753 case AST_ADD
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) + children
[1]->asReal(sign_hint
); break;
2754 case AST_SUB
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) - children
[1]->asReal(sign_hint
); break;
2755 case AST_MUL
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) * children
[1]->asReal(sign_hint
); break;
2756 case AST_DIV
: newNode
->realvalue
= children
[0]->asReal(sign_hint
) / children
[1]->asReal(sign_hint
); break;
2757 case AST_MOD
: newNode
->realvalue
= fmod(children
[0]->asReal(sign_hint
), children
[1]->asReal(sign_hint
)); break;
2758 default: log_abort();
2762 if (0) { case AST_POS
: const_func
= RTLIL::const_pos
; }
2763 if (0) { case AST_NEG
: const_func
= RTLIL::const_neg
; }
2764 if (children
[0]->type
== AST_CONSTANT
) {
2765 RTLIL::Const y
= const_func(children
[0]->bitsAsConst(width_hint
, sign_hint
), dummy_arg
, sign_hint
, false, width_hint
);
2766 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2768 if (children
[0]->isConst()) {
2769 newNode
= new AstNode(AST_REALVALUE
);
2770 if (type
== AST_POS
)
2771 newNode
->realvalue
= +children
[0]->asReal(sign_hint
);
2773 newNode
->realvalue
= -children
[0]->asReal(sign_hint
);
2777 if (children
[0]->isConst())
2779 bool found_sure_true
= false;
2780 bool found_maybe_true
= false;
2782 if (children
[0]->type
== AST_CONSTANT
)
2783 for (auto &bit
: children
[0]->bits
) {
2784 if (bit
== RTLIL::State::S1
)
2785 found_sure_true
= true;
2786 if (bit
> RTLIL::State::S1
)
2787 found_maybe_true
= true;
2790 found_sure_true
= children
[0]->asReal(sign_hint
) != 0;
2792 AstNode
*choice
= NULL
, *not_choice
= NULL
;
2793 if (found_sure_true
)
2794 choice
= children
[1], not_choice
= children
[2];
2795 else if (!found_maybe_true
)
2796 choice
= children
[2], not_choice
= children
[1];
2798 if (choice
!= NULL
) {
2799 if (choice
->type
== AST_CONSTANT
) {
2800 int other_width_hint
= width_hint
;
2801 bool other_sign_hint
= sign_hint
, other_real
= false;
2802 not_choice
->detectSignWidth(other_width_hint
, other_sign_hint
, &other_real
);
2804 newNode
= new AstNode(AST_REALVALUE
);
2805 choice
->detectSignWidth(width_hint
, sign_hint
);
2806 newNode
->realvalue
= choice
->asReal(sign_hint
);
2808 RTLIL::Const y
= choice
->bitsAsConst(width_hint
, sign_hint
);
2809 if (choice
->is_string
&& y
.bits
.size() % 8 == 0 && sign_hint
== false)
2810 newNode
= mkconst_str(y
.bits
);
2812 newNode
= mkconst_bits(y
.bits
, sign_hint
);
2815 if (choice
->isConst()) {
2816 newNode
= choice
->clone();
2818 } else if (children
[1]->type
== AST_CONSTANT
&& children
[2]->type
== AST_CONSTANT
) {
2819 RTLIL::Const a
= children
[1]->bitsAsConst(width_hint
, sign_hint
);
2820 RTLIL::Const b
= children
[2]->bitsAsConst(width_hint
, sign_hint
);
2821 log_assert(a
.bits
.size() == b
.bits
.size());
2822 for (size_t i
= 0; i
< a
.bits
.size(); i
++)
2823 if (a
.bits
[i
] != b
.bits
[i
])
2824 a
.bits
[i
] = RTLIL::State::Sx
;
2825 newNode
= mkconst_bits(a
.bits
, sign_hint
);
2826 } else if (children
[1]->isConst() && children
[2]->isConst()) {
2827 newNode
= new AstNode(AST_REALVALUE
);
2828 if (children
[1]->asReal(sign_hint
) == children
[2]->asReal(sign_hint
))
2829 newNode
->realvalue
= children
[1]->asReal(sign_hint
);
2831 // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
2832 // the data type in question should be returned if the ?: is ambiguous. The
2833 // value in Table 7-1 for the 'real' type is 0.0.
2834 newNode
->realvalue
= 0.0;
2839 string_op
= !children
.empty();
2840 for (auto it
= children
.begin(); it
!= children
.end(); it
++) {
2841 if ((*it
)->type
!= AST_CONSTANT
)
2843 if (!(*it
)->is_string
)
2845 tmp_bits
.insert(tmp_bits
.end(), (*it
)->bits
.begin(), (*it
)->bits
.end());
2847 newNode
= string_op
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
2850 if (children
.at(0)->type
!= AST_CONSTANT
|| children
.at(1)->type
!= AST_CONSTANT
)
2852 for (int i
= 0; i
< children
[0]->bitsAsConst().as_int(); i
++)
2853 tmp_bits
.insert(tmp_bits
.end(), children
.at(1)->bits
.begin(), children
.at(1)->bits
.end());
2854 newNode
= children
.at(1)->is_string
? mkconst_str(tmp_bits
) : mkconst_bits(tmp_bits
, false);
2862 // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
2865 // fprintf(stderr, "----\n");
2866 // dumpAst(stderr, "- ");
2867 // newNode->dumpAst(stderr, "+ ");
2868 log_assert(newNode
!= NULL
);
2869 newNode
->filename
= filename
;
2870 newNode
->linenum
= linenum
;
2871 newNode
->cloneInto(this);
2873 did_something
= true;
2879 recursion_counter
--;
2880 return did_something
;
2883 static void replace_result_wire_name_in_function(AstNode
*node
, std::string
&from
, std::string
&to
)
2885 for (auto &it
: node
->children
)
2886 replace_result_wire_name_in_function(it
, from
, to
);
2887 if (node
->str
== from
)
2891 // replace a readmem[bh] TCALL ast node with a block of memory assignments
2892 AstNode
*AstNode::readmem(bool is_readmemh
, std::string mem_filename
, AstNode
*memory
, int start_addr
, int finish_addr
, bool unconditional_init
)
2894 int mem_width
, mem_size
, addr_bits
;
2895 memory
->meminfo(mem_width
, mem_size
, addr_bits
);
2897 AstNode
*block
= new AstNode(AST_BLOCK
);
2899 AstNode
*meminit
= nullptr;
2900 int next_meminit_cursor
=0;
2901 vector
<State
> meminit_bits
;
2905 f
.open(mem_filename
.c_str());
2912 std::string path
= filename
.substr(0, filename
.find_last_of(slash
)+1);
2913 f
.open(path
+ mem_filename
.c_str());
2914 yosys_input_files
.insert(path
+ mem_filename
);
2916 yosys_input_files
.insert(mem_filename
);
2918 if (f
.fail() || GetSize(mem_filename
) == 0)
2919 log_file_error(filename
, linenum
, "Can not open file `%s` for %s.\n", mem_filename
.c_str(), str
.c_str());
2921 log_assert(GetSize(memory
->children
) == 2 && memory
->children
[1]->type
== AST_RANGE
&& memory
->children
[1]->range_valid
);
2922 int range_left
= memory
->children
[1]->range_left
, range_right
= memory
->children
[1]->range_right
;
2923 int range_min
= min(range_left
, range_right
), range_max
= max(range_left
, range_right
);
2926 start_addr
= range_min
;
2928 if (finish_addr
< 0)
2929 finish_addr
= range_max
+ 1;
2931 bool in_comment
= false;
2932 int increment
= start_addr
<= finish_addr
? +1 : -1;
2933 int cursor
= start_addr
;
2937 std::string line
, token
;
2938 std::getline(f
, line
);
2940 for (int i
= 0; i
< GetSize(line
); i
++) {
2941 if (in_comment
&& line
.compare(i
, 2, "*/") == 0) {
2947 if (!in_comment
&& line
.compare(i
, 2, "/*") == 0)
2955 token
= next_token(line
, " \t\r\n");
2956 if (token
.empty() || token
.compare(0, 2, "//") == 0)
2959 if (token
[0] == '@') {
2960 token
= token
.substr(1);
2961 const char *nptr
= token
.c_str();
2963 cursor
= strtol(nptr
, &endptr
, 16);
2964 if (!*nptr
|| *endptr
)
2965 log_file_error(filename
, linenum
, "Can not parse address `%s` for %s.\n", nptr
, str
.c_str());
2969 AstNode
*value
= VERILOG_FRONTEND::const2ast(stringf("%d'%c", mem_width
, is_readmemh
? 'h' : 'b') + token
);
2971 if (unconditional_init
)
2973 if (meminit
== nullptr || cursor
!= next_meminit_cursor
)
2975 if (meminit
!= nullptr) {
2976 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
2977 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
2980 meminit
= new AstNode(AST_MEMINIT
);
2981 meminit
->children
.push_back(AstNode::mkconst_int(cursor
, false));
2982 meminit
->children
.push_back(nullptr);
2983 meminit
->children
.push_back(nullptr);
2984 meminit
->str
= memory
->str
;
2985 meminit
->id2ast
= memory
;
2986 meminit_bits
.clear();
2989 current_ast_mod
->children
.push_back(meminit
);
2990 next_meminit_cursor
= cursor
;
2994 next_meminit_cursor
++;
2995 meminit_bits
.insert(meminit_bits
.end(), value
->bits
.begin(), value
->bits
.end());
3000 block
->children
.push_back(new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
, new AstNode(AST_RANGE
, AstNode::mkconst_int(cursor
, false))), value
));
3001 block
->children
.back()->children
[0]->str
= memory
->str
;
3002 block
->children
.back()->children
[0]->id2ast
= memory
;
3003 block
->children
.back()->children
[0]->was_checked
= true;
3006 cursor
+= increment
;
3007 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
3011 if ((cursor
== finish_addr
+increment
) || (increment
> 0 && cursor
> range_max
) || (increment
< 0 && cursor
< range_min
))
3015 if (meminit
!= nullptr) {
3016 meminit
->children
[1] = AstNode::mkconst_bits(meminit_bits
, false);
3017 meminit
->children
[2] = AstNode::mkconst_int(meminit_size
, false);
3023 // annotate the names of all wires and other named objects in a generate block
3024 void AstNode::expand_genblock(std::string index_var
, std::string prefix
, std::map
<std::string
, std::string
> &name_map
)
3026 if (!index_var
.empty() && type
== AST_IDENTIFIER
&& str
== index_var
) {
3027 if (children
.empty()) {
3028 current_scope
[index_var
]->children
[0]->cloneInto(this);
3030 AstNode
*p
= new AstNode(AST_LOCALPARAM
, current_scope
[index_var
]->children
[0]->clone());
3031 p
->str
= stringf("$genval$%d", autoidx
++);
3032 current_ast_mod
->children
.push_back(p
);
3036 auto resolved
= current_scope
.at(index_var
);
3037 if (resolved
->range_valid
) {
3038 p
->range_left
= resolved
->range_left
;
3039 p
->range_right
= resolved
->range_right
;
3040 p
->range_swapped
= resolved
->range_swapped
;
3041 p
->range_valid
= resolved
->range_valid
;
3046 if ((type
== AST_IDENTIFIER
|| type
== AST_FCALL
|| type
== AST_TCALL
|| type
== AST_WIRETYPE
) && name_map
.count(str
) > 0)
3047 str
= name_map
[str
];
3049 std::map
<std::string
, std::string
> backup_name_map
;
3051 for (size_t i
= 0; i
< children
.size(); i
++) {
3052 AstNode
*child
= children
[i
];
3053 if (child
->type
== AST_WIRE
|| child
->type
== AST_MEMORY
|| child
->type
== AST_PARAMETER
|| child
->type
== AST_LOCALPARAM
||
3054 child
->type
== AST_FUNCTION
|| child
->type
== AST_TASK
|| child
->type
== AST_CELL
|| child
->type
== AST_TYPEDEF
) {
3055 if (backup_name_map
.size() == 0)
3056 backup_name_map
= name_map
;
3057 std::string new_name
= prefix
[0] == '\\' ? prefix
.substr(1) : prefix
;
3058 size_t pos
= child
->str
.rfind('.');
3059 if (pos
== std::string::npos
)
3060 pos
= child
->str
[0] == '\\' && prefix
[0] == '\\' ? 1 : 0;
3063 new_name
= child
->str
.substr(0, pos
) + new_name
+ child
->str
.substr(pos
);
3064 if (new_name
[0] != '$' && new_name
[0] != '\\')
3065 new_name
= prefix
[0] + new_name
;
3066 name_map
[child
->str
] = new_name
;
3067 if (child
->type
== AST_FUNCTION
)
3068 replace_result_wire_name_in_function(child
, child
->str
, new_name
);
3070 child
->str
= new_name
;
3071 current_scope
[new_name
] = child
;
3075 for (size_t i
= 0; i
< children
.size(); i
++) {
3076 AstNode
*child
= children
[i
];
3077 // AST_PREFIX member names should not be prefixed; a nested AST_PREFIX
3078 // still needs to recursed-into
3079 if (type
== AST_PREFIX
&& i
== 1 && child
->type
== AST_IDENTIFIER
)
3081 if (child
->type
!= AST_FUNCTION
&& child
->type
!= AST_TASK
)
3082 child
->expand_genblock(index_var
, prefix
, name_map
);
3086 if (backup_name_map
.size() > 0)
3087 name_map
.swap(backup_name_map
);
3090 // rename stuff (used when tasks of functions are instantiated)
3091 void AstNode::replace_ids(const std::string
&prefix
, const std::map
<std::string
, std::string
> &rules
)
3093 if (type
== AST_BLOCK
)
3095 std::map
<std::string
, std::string
> new_rules
= rules
;
3096 std::string new_prefix
= prefix
+ str
;
3098 for (auto child
: children
)
3099 if (child
->type
== AST_WIRE
) {
3100 new_rules
[child
->str
] = new_prefix
+ child
->str
;
3101 child
->str
= new_prefix
+ child
->str
;
3104 for (auto child
: children
)
3105 if (child
->type
!= AST_WIRE
)
3106 child
->replace_ids(new_prefix
, new_rules
);
3110 if (type
== AST_IDENTIFIER
&& rules
.count(str
) > 0)
3111 str
= rules
.at(str
);
3112 for (auto child
: children
)
3113 child
->replace_ids(prefix
, rules
);
3117 // helper function for mem2reg_as_needed_pass1
3118 static void mark_memories_assign_lhs_complex(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
3119 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, AstNode
*that
)
3121 for (auto &child
: that
->children
)
3122 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, child
);
3124 if (that
->type
== AST_IDENTIFIER
&& that
->id2ast
&& that
->id2ast
->type
== AST_MEMORY
) {
3125 AstNode
*mem
= that
->id2ast
;
3126 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_CMPLX_LHS
))
3127 mem2reg_places
[mem
].insert(stringf("%s:%d", that
->filename
.c_str(), that
->linenum
));
3128 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CMPLX_LHS
;
3132 // find memories that should be replaced by registers
3133 void AstNode::mem2reg_as_needed_pass1(dict
<AstNode
*, pool
<std::string
>> &mem2reg_places
,
3134 dict
<AstNode
*, uint32_t> &mem2reg_candidates
, dict
<AstNode
*, uint32_t> &proc_flags
, uint32_t &flags
)
3136 uint32_t children_flags
= 0;
3137 int lhs_children_counter
= 0;
3139 if (type
== AST_TYPEDEF
)
3140 return; // don't touch content of typedefs
3142 if (type
== AST_ASSIGN
|| type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
)
3144 // mark all memories that are used in a complex expression on the left side of an assignment
3145 for (auto &lhs_child
: children
[0]->children
)
3146 mark_memories_assign_lhs_complex(mem2reg_places
, mem2reg_candidates
, lhs_child
);
3148 if (children
[0]->type
== AST_IDENTIFIER
&& children
[0]->id2ast
&& children
[0]->id2ast
->type
== AST_MEMORY
)
3150 AstNode
*mem
= children
[0]->id2ast
;
3152 // activate mem2reg if this is assigned in an async proc
3153 if (flags
& AstNode::MEM2REG_FL_ASYNC
) {
3154 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ASYNC
))
3155 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3156 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ASYNC
;
3159 // remember if this is assigned blocking (=)
3160 if (type
== AST_ASSIGN_EQ
) {
3161 if (!(proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
))
3162 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3163 proc_flags
[mem
] |= AstNode::MEM2REG_FL_EQ1
;
3166 // for proper (non-init) writes: remember if this is a constant index or not
3167 if ((flags
& MEM2REG_FL_INIT
) == 0) {
3168 if (children
[0]->children
.size() && children
[0]->children
[0]->type
== AST_RANGE
&& children
[0]->children
[0]->children
.size()) {
3169 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
)
3170 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_CONST_LHS
;
3172 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_VAR_LHS
;
3176 // remember where this is
3177 if (flags
& MEM2REG_FL_INIT
) {
3178 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_INIT
))
3179 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3180 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_INIT
;
3182 if (!(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_SET_ELSE
))
3183 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3184 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_SET_ELSE
;
3188 lhs_children_counter
= 1;
3191 if (type
== AST_IDENTIFIER
&& id2ast
&& id2ast
->type
== AST_MEMORY
)
3193 AstNode
*mem
= id2ast
;
3195 // flag if used after blocking assignment (in same proc)
3196 if ((proc_flags
[mem
] & AstNode::MEM2REG_FL_EQ1
) && !(mem2reg_candidates
[mem
] & AstNode::MEM2REG_FL_EQ2
)) {
3197 mem2reg_places
[mem
].insert(stringf("%s:%d", filename
.c_str(), linenum
));
3198 mem2reg_candidates
[mem
] |= AstNode::MEM2REG_FL_EQ2
;
3202 // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg'
3203 if (type
== AST_MEMORY
&& (get_bool_attribute("\\mem2reg") || (flags
& AstNode::MEM2REG_FL_ALL
) || !is_reg
))
3204 mem2reg_candidates
[this] |= AstNode::MEM2REG_FL_FORCED
;
3206 if (type
== AST_MODULE
&& get_bool_attribute("\\mem2reg"))
3207 children_flags
|= AstNode::MEM2REG_FL_ALL
;
3209 dict
<AstNode
*, uint32_t> *proc_flags_p
= NULL
;
3211 if (type
== AST_ALWAYS
) {
3212 int count_edge_events
= 0;
3213 for (auto child
: children
)
3214 if (child
->type
== AST_POSEDGE
|| child
->type
== AST_NEGEDGE
)
3215 count_edge_events
++;
3216 if (count_edge_events
!= 1)
3217 children_flags
|= AstNode::MEM2REG_FL_ASYNC
;
3218 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
3221 if (type
== AST_INITIAL
) {
3222 children_flags
|= AstNode::MEM2REG_FL_INIT
;
3223 proc_flags_p
= new dict
<AstNode
*, uint32_t>;
3226 uint32_t backup_flags
= flags
;
3227 flags
|= children_flags
;
3228 log_assert((flags
& ~0x000000ff) == 0);
3230 for (auto child
: children
)
3232 if (lhs_children_counter
> 0) {
3233 lhs_children_counter
--;
3234 if (child
->children
.size() && child
->children
[0]->type
== AST_RANGE
&& child
->children
[0]->children
.size()) {
3235 for (auto c
: child
->children
[0]->children
) {
3237 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
3239 c
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
3244 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, *proc_flags_p
, flags
);
3246 child
->mem2reg_as_needed_pass1(mem2reg_places
, mem2reg_candidates
, proc_flags
, flags
);
3249 flags
&= ~children_flags
| backup_flags
;
3253 for (auto it
: *proc_flags_p
)
3254 log_assert((it
.second
& ~0xff000000) == 0);
3256 delete proc_flags_p
;
3260 bool AstNode::mem2reg_check(pool
<AstNode
*> &mem2reg_set
)
3262 if (type
!= AST_IDENTIFIER
|| !id2ast
|| !mem2reg_set
.count(id2ast
))
3265 if (children
.empty() || children
[0]->type
!= AST_RANGE
|| GetSize(children
[0]->children
) != 1)
3266 log_file_error(filename
, linenum
, "Invalid array access.\n");
3271 void AstNode::mem2reg_remove(pool
<AstNode
*> &mem2reg_set
, vector
<AstNode
*> &delnodes
)
3273 log_assert(mem2reg_set
.count(this) == 0);
3275 if (mem2reg_set
.count(id2ast
))
3278 for (size_t i
= 0; i
< children
.size(); i
++) {
3279 if (mem2reg_set
.count(children
[i
]) > 0) {
3280 delnodes
.push_back(children
[i
]);
3281 children
.erase(children
.begin() + (i
--));
3283 children
[i
]->mem2reg_remove(mem2reg_set
, delnodes
);
3288 // actually replace memories with registers
3289 bool AstNode::mem2reg_as_needed_pass2(pool
<AstNode
*> &mem2reg_set
, AstNode
*mod
, AstNode
*block
, AstNode
*&async_block
)
3291 bool did_something
= false;
3293 if (type
== AST_BLOCK
)
3296 if (type
== AST_FUNCTION
|| type
== AST_TASK
)
3299 if (type
== AST_TYPEDEF
)
3302 if (type
== AST_MEMINIT
&& id2ast
&& mem2reg_set
.count(id2ast
))
3304 log_assert(children
[0]->type
== AST_CONSTANT
);
3305 log_assert(children
[1]->type
== AST_CONSTANT
);
3306 log_assert(children
[2]->type
== AST_CONSTANT
);
3308 int cursor
= children
[0]->asInt(false);
3309 Const data
= children
[1]->bitsAsConst();
3310 int length
= children
[2]->asInt(false);
3314 AstNode
*block
= new AstNode(AST_INITIAL
, new AstNode(AST_BLOCK
));
3315 mod
->children
.push_back(block
);
3316 block
= block
->children
[0];
3318 int wordsz
= GetSize(data
) / length
;
3320 for (int i
= 0; i
< length
; i
++) {
3321 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)));
3322 block
->children
.back()->children
[0]->str
= str
;
3323 block
->children
.back()->children
[0]->id2ast
= id2ast
;
3324 block
->children
.back()->children
[0]->was_checked
= true;
3328 AstNode
*newNode
= new AstNode(AST_NONE
);
3329 newNode
->cloneInto(this);
3332 did_something
= true;
3335 if (type
== AST_ASSIGN
&& block
== NULL
&& children
[0]->mem2reg_check(mem2reg_set
))
3337 if (async_block
== NULL
) {
3338 async_block
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
3339 mod
->children
.push_back(async_block
);
3342 AstNode
*newNode
= clone();
3343 newNode
->type
= AST_ASSIGN_EQ
;
3344 newNode
->children
[0]->was_checked
= true;
3345 async_block
->children
[0]->children
.push_back(newNode
);
3347 newNode
= new AstNode(AST_NONE
);
3348 newNode
->cloneInto(this);
3351 did_something
= true;
3354 if ((type
== AST_ASSIGN_LE
|| type
== AST_ASSIGN_EQ
) && children
[0]->mem2reg_check(mem2reg_set
) &&
3355 children
[0]->children
[0]->children
[0]->type
!= AST_CONSTANT
)
3357 std::stringstream sstr
;
3358 sstr
<< "$mem2reg_wr$" << children
[0]->str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
3359 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
3361 int mem_width
, mem_size
, addr_bits
;
3362 bool mem_signed
= children
[0]->id2ast
->is_signed
;
3363 children
[0]->id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
3365 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
3366 wire_addr
->str
= id_addr
;
3367 wire_addr
->is_reg
= true;
3368 wire_addr
->was_checked
= true;
3369 wire_addr
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3370 mod
->children
.push_back(wire_addr
);
3371 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
3373 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
3374 wire_data
->str
= id_data
;
3375 wire_data
->is_reg
= true;
3376 wire_data
->was_checked
= true;
3377 wire_data
->is_signed
= mem_signed
;
3378 wire_data
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3379 mod
->children
.push_back(wire_data
);
3380 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
3382 log_assert(block
!= NULL
);
3383 size_t assign_idx
= 0;
3384 while (assign_idx
< block
->children
.size() && block
->children
[assign_idx
] != this)
3386 log_assert(assign_idx
< block
->children
.size());
3388 AstNode
*assign_addr
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->children
[0]->clone());
3389 assign_addr
->children
[0]->str
= id_addr
;
3390 assign_addr
->children
[0]->was_checked
= true;
3391 block
->children
.insert(block
->children
.begin()+assign_idx
+1, assign_addr
);
3393 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
3394 case_node
->children
[0]->str
= id_addr
;
3395 for (int i
= 0; i
< mem_size
; i
++) {
3396 if (children
[0]->children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->children
[0]->integer
) != i
)
3398 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
3399 AstNode
*assign_reg
= new AstNode(type
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
3400 if (children
[0]->children
.size() == 2)
3401 assign_reg
->children
[0]->children
.push_back(children
[0]->children
[1]->clone());
3402 assign_reg
->children
[0]->str
= stringf("%s[%d]", children
[0]->str
.c_str(), i
);
3403 assign_reg
->children
[1]->str
= id_data
;
3404 cond_node
->children
[1]->children
.push_back(assign_reg
);
3405 case_node
->children
.push_back(cond_node
);
3407 block
->children
.insert(block
->children
.begin()+assign_idx
+2, case_node
);
3409 children
[0]->delete_children();
3410 children
[0]->range_valid
= false;
3411 children
[0]->id2ast
= NULL
;
3412 children
[0]->str
= id_data
;
3413 type
= AST_ASSIGN_EQ
;
3414 children
[0]->was_checked
= true;
3416 did_something
= true;
3419 if (mem2reg_check(mem2reg_set
))
3421 AstNode
*bit_part_sel
= NULL
;
3422 if (children
.size() == 2)
3423 bit_part_sel
= children
[1]->clone();
3425 if (children
[0]->children
[0]->type
== AST_CONSTANT
)
3427 int id
= children
[0]->children
[0]->integer
;
3428 str
= stringf("%s[%d]", str
.c_str(), id
);
3431 range_valid
= false;
3436 std::stringstream sstr
;
3437 sstr
<< "$mem2reg_rd$" << str
<< "$" << filename
<< ":" << linenum
<< "$" << (autoidx
++);
3438 std::string id_addr
= sstr
.str() + "_ADDR", id_data
= sstr
.str() + "_DATA";
3440 int mem_width
, mem_size
, addr_bits
;
3441 bool mem_signed
= id2ast
->is_signed
;
3442 id2ast
->meminfo(mem_width
, mem_size
, addr_bits
);
3444 AstNode
*wire_addr
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(addr_bits
-1, true), mkconst_int(0, true)));
3445 wire_addr
->str
= id_addr
;
3446 wire_addr
->is_reg
= true;
3447 wire_addr
->was_checked
= true;
3449 wire_addr
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3450 mod
->children
.push_back(wire_addr
);
3451 while (wire_addr
->simplify(true, false, false, 1, -1, false, false)) { }
3453 AstNode
*wire_data
= new AstNode(AST_WIRE
, new AstNode(AST_RANGE
, mkconst_int(mem_width
-1, true), mkconst_int(0, true)));
3454 wire_data
->str
= id_data
;
3455 wire_data
->is_reg
= true;
3456 wire_data
->was_checked
= true;
3457 wire_data
->is_signed
= mem_signed
;
3459 wire_data
->attributes
["\\nosync"] = AstNode::mkconst_int(1, false);
3460 mod
->children
.push_back(wire_data
);
3461 while (wire_data
->simplify(true, false, false, 1, -1, false, false)) { }
3463 AstNode
*assign_addr
= new AstNode(block
? AST_ASSIGN_EQ
: AST_ASSIGN
, new AstNode(AST_IDENTIFIER
), children
[0]->children
[0]->clone());
3464 assign_addr
->children
[0]->str
= id_addr
;
3465 assign_addr
->children
[0]->was_checked
= true;
3467 AstNode
*case_node
= new AstNode(AST_CASE
, new AstNode(AST_IDENTIFIER
));
3468 case_node
->children
[0]->str
= id_addr
;
3470 for (int i
= 0; i
< mem_size
; i
++) {
3471 if (children
[0]->children
[0]->type
== AST_CONSTANT
&& int(children
[0]->children
[0]->integer
) != i
)
3473 AstNode
*cond_node
= new AstNode(AST_COND
, AstNode::mkconst_int(i
, false, addr_bits
), new AstNode(AST_BLOCK
));
3474 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), new AstNode(AST_IDENTIFIER
));
3475 assign_reg
->children
[0]->str
= id_data
;
3476 assign_reg
->children
[0]->was_checked
= true;
3477 assign_reg
->children
[1]->str
= stringf("%s[%d]", str
.c_str(), i
);
3478 cond_node
->children
[1]->children
.push_back(assign_reg
);
3479 case_node
->children
.push_back(cond_node
);
3482 std::vector
<RTLIL::State
> x_bits
;
3483 for (int i
= 0; i
< mem_width
; i
++)
3484 x_bits
.push_back(RTLIL::State::Sx
);
3486 AstNode
*cond_node
= new AstNode(AST_COND
, new AstNode(AST_DEFAULT
), new AstNode(AST_BLOCK
));
3487 AstNode
*assign_reg
= new AstNode(AST_ASSIGN_EQ
, new AstNode(AST_IDENTIFIER
), AstNode::mkconst_bits(x_bits
, false));
3488 assign_reg
->children
[0]->str
= id_data
;
3489 assign_reg
->children
[0]->was_checked
= true;
3490 cond_node
->children
[1]->children
.push_back(assign_reg
);
3491 case_node
->children
.push_back(cond_node
);
3495 size_t assign_idx
= 0;
3496 while (assign_idx
< block
->children
.size() && !block
->children
[assign_idx
]->contains(this))
3498 log_assert(assign_idx
< block
->children
.size());
3499 block
->children
.insert(block
->children
.begin()+assign_idx
, case_node
);
3500 block
->children
.insert(block
->children
.begin()+assign_idx
, assign_addr
);
3504 AstNode
*proc
= new AstNode(AST_ALWAYS
, new AstNode(AST_BLOCK
));
3505 proc
->children
[0]->children
.push_back(case_node
);
3506 mod
->children
.push_back(proc
);
3507 mod
->children
.push_back(assign_addr
);
3511 range_valid
= false;
3517 children
.push_back(bit_part_sel
);
3519 did_something
= true;
3522 log_assert(id2ast
== NULL
|| mem2reg_set
.count(id2ast
) == 0);
3524 auto children_list
= children
;
3525 for (size_t i
= 0; i
< children_list
.size(); i
++)
3526 if (children_list
[i
]->mem2reg_as_needed_pass2(mem2reg_set
, mod
, block
, async_block
))
3527 did_something
= true;
3529 return did_something
;
3532 // calculate memory dimensions
3533 void AstNode::meminfo(int &mem_width
, int &mem_size
, int &addr_bits
)
3535 log_assert(type
== AST_MEMORY
);
3537 mem_width
= children
[0]->range_left
- children
[0]->range_right
+ 1;
3538 mem_size
= children
[1]->range_left
- children
[1]->range_right
;
3542 mem_size
+= min(children
[1]->range_left
, children
[1]->range_right
) + 1;
3545 while ((1 << addr_bits
) < mem_size
)
3549 bool AstNode::has_const_only_constructs(bool &recommend_const_eval
)
3551 if (type
== AST_FOR
)
3552 recommend_const_eval
= true;
3553 if (type
== AST_WHILE
|| type
== AST_REPEAT
)
3555 if (type
== AST_FCALL
&& current_scope
.count(str
))
3556 if (current_scope
[str
]->has_const_only_constructs(recommend_const_eval
))
3558 for (auto child
: children
)
3559 if (child
->AstNode::has_const_only_constructs(recommend_const_eval
))
3564 bool AstNode::is_simple_const_expr()
3566 if (type
== AST_IDENTIFIER
)
3568 for (auto child
: children
)
3569 if (!child
->is_simple_const_expr())
3574 // helper function for AstNode::eval_const_function()
3575 void AstNode::replace_variables(std::map
<std::string
, AstNode::varinfo_t
> &variables
, AstNode
*fcall
)
3577 if (type
== AST_IDENTIFIER
&& variables
.count(str
)) {
3578 int offset
= variables
.at(str
).offset
, width
= variables
.at(str
).val
.bits
.size();
3579 if (!children
.empty()) {
3580 if (children
.size() != 1 || children
.at(0)->type
!= AST_RANGE
)
3581 log_file_error(filename
, linenum
, "Memory access in constant function is not supported\n%s:%d: ...called from here.\n",
3582 fcall
->filename
.c_str(), fcall
->linenum
);
3583 children
.at(0)->replace_variables(variables
, fcall
);
3584 while (simplify(true, false, false, 1, -1, false, true)) { }
3585 if (!children
.at(0)->range_valid
)
3586 log_file_error(filename
, linenum
, "Non-constant range\n%s:%d: ... called from here.\n",
3587 fcall
->filename
.c_str(), fcall
->linenum
);
3588 offset
= min(children
.at(0)->range_left
, children
.at(0)->range_right
);
3589 width
= min(std::abs(children
.at(0)->range_left
- children
.at(0)->range_right
) + 1, width
);
3591 offset
-= variables
.at(str
).offset
;
3592 std::vector
<RTLIL::State
> &var_bits
= variables
.at(str
).val
.bits
;
3593 std::vector
<RTLIL::State
> new_bits(var_bits
.begin() + offset
, var_bits
.begin() + offset
+ width
);
3594 AstNode
*newNode
= mkconst_bits(new_bits
, variables
.at(str
).is_signed
);
3595 newNode
->cloneInto(this);
3600 for (auto &child
: children
)
3601 child
->replace_variables(variables
, fcall
);
3604 // evaluate functions with all-const arguments
3605 AstNode
*AstNode::eval_const_function(AstNode
*fcall
)
3607 std::map
<std::string
, AstNode
*> backup_scope
;
3608 std::map
<std::string
, AstNode::varinfo_t
> variables
;
3609 AstNode
*block
= new AstNode(AST_BLOCK
);
3612 for (auto child
: children
)
3614 if (child
->type
== AST_WIRE
)
3616 while (child
->simplify(true, false, false, 1, -1, false, true)) { }
3617 if (!child
->range_valid
)
3618 log_file_error(child
->filename
, child
->linenum
, "Can't determine size of variable %s\n%s:%d: ... called from here.\n",
3619 child
->str
.c_str(), fcall
->filename
.c_str(), fcall
->linenum
);
3620 variables
[child
->str
].val
= RTLIL::Const(RTLIL::State::Sx
, abs(child
->range_left
- child
->range_right
)+1);
3621 variables
[child
->str
].offset
= min(child
->range_left
, child
->range_right
);
3622 variables
[child
->str
].is_signed
= child
->is_signed
;
3623 if (child
->is_input
&& argidx
< fcall
->children
.size())
3624 variables
[child
->str
].val
= fcall
->children
.at(argidx
++)->bitsAsConst(variables
[child
->str
].val
.bits
.size());
3625 backup_scope
[child
->str
] = current_scope
[child
->str
];
3626 current_scope
[child
->str
] = child
;
3630 block
->children
.push_back(child
->clone());
3633 log_assert(variables
.count(str
) != 0);
3635 while (!block
->children
.empty())
3637 AstNode
*stmt
= block
->children
.front();
3640 log("-----------------------------------\n");
3641 for (auto &it
: variables
)
3642 log("%20s %40s\n", it
.first
.c_str(), log_signal(it
.second
.val
));
3643 stmt
->dumpAst(NULL
, "stmt> ");
3646 if (stmt
->type
== AST_ASSIGN_EQ
)
3648 if (stmt
->children
.at(0)->type
== AST_IDENTIFIER
&& stmt
->children
.at(0)->children
.size() != 0 &&
3649 stmt
->children
.at(0)->children
.at(0)->type
== AST_RANGE
)
3650 stmt
->children
.at(0)->children
.at(0)->replace_variables(variables
, fcall
);
3651 stmt
->children
.at(1)->replace_variables(variables
, fcall
);
3652 while (stmt
->simplify(true, false, false, 1, -1, false, true)) { }
3654 if (stmt
->type
!= AST_ASSIGN_EQ
)
3657 if (stmt
->children
.at(1)->type
!= AST_CONSTANT
)
3658 log_file_error(stmt
->filename
, stmt
->linenum
, "Non-constant expression in constant function\n%s:%d: ... called from here. X\n",
3659 fcall
->filename
.c_str(), fcall
->linenum
);
3661 if (stmt
->children
.at(0)->type
!= AST_IDENTIFIER
)
3662 log_file_error(stmt
->filename
, stmt
->linenum
, "Unsupported composite left hand side in constant function\n%s:%d: ... called from here.\n",
3663 fcall
->filename
.c_str(), fcall
->linenum
);
3665 if (!variables
.count(stmt
->children
.at(0)->str
))
3666 log_file_error(stmt
->filename
, stmt
->linenum
, "Assignment to non-local variable in constant function\n%s:%d: ... called from here.\n",
3667 fcall
->filename
.c_str(), fcall
->linenum
);
3669 if (stmt
->children
.at(0)->children
.empty()) {
3670 variables
[stmt
->children
.at(0)->str
].val
= stmt
->children
.at(1)->bitsAsConst(variables
[stmt
->children
.at(0)->str
].val
.bits
.size());
3672 AstNode
*range
= stmt
->children
.at(0)->children
.at(0);
3673 if (!range
->range_valid
)
3674 log_file_error(range
->filename
, range
->linenum
, "Non-constant range\n%s:%d: ... called from here.\n",
3675 fcall
->filename
.c_str(), fcall
->linenum
);
3676 int offset
= min(range
->range_left
, range
->range_right
);
3677 int width
= std::abs(range
->range_left
- range
->range_right
) + 1;
3678 varinfo_t
&v
= variables
[stmt
->children
.at(0)->str
];
3679 RTLIL::Const r
= stmt
->children
.at(1)->bitsAsConst(v
.val
.bits
.size());
3680 for (int i
= 0; i
< width
; i
++)
3681 v
.val
.bits
.at(i
+offset
-v
.offset
) = r
.bits
.at(i
);
3684 delete block
->children
.front();
3685 block
->children
.erase(block
->children
.begin());
3689 if (stmt
->type
== AST_FOR
)
3691 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(0));
3692 stmt
->children
.at(3)->children
.push_back(stmt
->children
.at(2));
3693 stmt
->children
.erase(stmt
->children
.begin() + 2);
3694 stmt
->children
.erase(stmt
->children
.begin());
3695 stmt
->type
= AST_WHILE
;
3699 if (stmt
->type
== AST_WHILE
)
3701 AstNode
*cond
= stmt
->children
.at(0)->clone();
3702 cond
->replace_variables(variables
, fcall
);
3703 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
3705 if (cond
->type
!= AST_CONSTANT
)
3706 log_file_error(stmt
->filename
, stmt
->linenum
, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
3707 fcall
->filename
.c_str(), fcall
->linenum
);
3709 if (cond
->asBool()) {
3710 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
3712 delete block
->children
.front();
3713 block
->children
.erase(block
->children
.begin());
3720 if (stmt
->type
== AST_REPEAT
)
3722 AstNode
*num
= stmt
->children
.at(0)->clone();
3723 num
->replace_variables(variables
, fcall
);
3724 while (num
->simplify(true, false, false, 1, -1, false, true)) { }
3726 if (num
->type
!= AST_CONSTANT
)
3727 log_file_error(stmt
->filename
, stmt
->linenum
, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
3728 fcall
->filename
.c_str(), fcall
->linenum
);
3730 block
->children
.erase(block
->children
.begin());
3731 for (int i
= 0; i
< num
->bitsAsConst().as_int(); i
++)
3732 block
->children
.insert(block
->children
.begin(), stmt
->children
.at(1)->clone());
3739 if (stmt
->type
== AST_CASE
)
3741 AstNode
*expr
= stmt
->children
.at(0)->clone();
3742 expr
->replace_variables(variables
, fcall
);
3743 while (expr
->simplify(true, false, false, 1, -1, false, true)) { }
3745 AstNode
*sel_case
= NULL
;
3746 for (size_t i
= 1; i
< stmt
->children
.size(); i
++)
3748 bool found_match
= false;
3749 log_assert(stmt
->children
.at(i
)->type
== AST_COND
|| stmt
->children
.at(i
)->type
== AST_CONDX
|| stmt
->children
.at(i
)->type
== AST_CONDZ
);
3751 if (stmt
->children
.at(i
)->children
.front()->type
== AST_DEFAULT
) {
3752 sel_case
= stmt
->children
.at(i
)->children
.back();
3756 for (size_t j
= 0; j
+1 < stmt
->children
.at(i
)->children
.size() && !found_match
; j
++)
3758 AstNode
*cond
= stmt
->children
.at(i
)->children
.at(j
)->clone();
3759 cond
->replace_variables(variables
, fcall
);
3761 cond
= new AstNode(AST_EQ
, expr
->clone(), cond
);
3762 while (cond
->simplify(true, false, false, 1, -1, false, true)) { }
3764 if (cond
->type
!= AST_CONSTANT
)
3765 log_file_error(stmt
->filename
, stmt
->linenum
, "Non-constant expression in constant function\n%s:%d: ... called from here.\n",
3766 fcall
->filename
.c_str(), fcall
->linenum
);
3768 found_match
= cond
->asBool();
3773 sel_case
= stmt
->children
.at(i
)->children
.back();
3778 block
->children
.erase(block
->children
.begin());
3780 block
->children
.insert(block
->children
.begin(), sel_case
->clone());
3786 if (stmt
->type
== AST_BLOCK
)
3788 block
->children
.erase(block
->children
.begin());
3789 block
->children
.insert(block
->children
.begin(), stmt
->children
.begin(), stmt
->children
.end());
3790 stmt
->children
.clear();
3795 log_file_error(stmt
->filename
, stmt
->linenum
, "Unsupported language construct in constant function\n%s:%d: ... called from here.\n",
3796 fcall
->filename
.c_str(), fcall
->linenum
);
3802 for (auto &it
: backup_scope
)
3803 if (it
.second
== NULL
)
3804 current_scope
.erase(it
.first
);
3806 current_scope
[it
.first
] = it
.second
;
3808 return AstNode::mkconst_bits(variables
.at(str
).val
.bits
, variables
.at(str
).is_signed
);