42 using namespace AST_INTERNAL;
50 bool AstNode::simplify(
bool const_fold,
bool at_zero,
bool in_lvalue,
int stage,
int width_hint,
bool sign_hint,
bool in_param)
56 log(
"-------------\n");
57 log(
"const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
58 int(const_fold),
int(at_zero),
int(in_lvalue),
int(stage),
int(width_hint),
int(sign_hint),
int(in_param));
66 while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { }
70 std::map<AstNode*, std::set<std::string>> mem2reg_places;
71 std::map<AstNode*, uint32_t> mem2reg_candidates, dummy_proc_flags;
73 mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, dummy_proc_flags, flags);
75 std::set<AstNode*> mem2reg_set;
76 for (
auto &it : mem2reg_candidates)
79 uint32_t memflags = it.second;
89 goto verbose_activate;
92 goto verbose_activate;
95 goto verbose_activate;
98 goto verbose_activate;
104 if (mem2reg_set.count(mem) == 0) {
105 log_warning(
"Replacing memory %s with list of registers.", mem->
str.c_str());
106 bool first_element =
true;
107 for (
auto &place : mem2reg_places[it.first]) {
108 log(
"%s%s", first_element ?
" See " :
", ", place.c_str());
109 first_element =
false;
116 mem2reg_set.insert(mem);
119 for (
auto node : mem2reg_set)
121 int mem_width, mem_size, addr_bits;
122 node->meminfo(mem_width, mem_size, addr_bits);
124 for (
int i = 0; i < mem_size; i++) {
126 mkconst_int(mem_width-1,
true), mkconst_int(0,
true)));
127 reg->
str =
stringf(
"%s[%d]", node->str.c_str(), i);
130 children.push_back(reg);
131 while (reg->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
135 mem2reg_as_needed_pass2(mem2reg_set,
this,
NULL);
137 for (
size_t i = 0; i < children.size(); i++) {
138 if (mem2reg_set.count(children[i]) > 0) {
140 children.erase(children.begin() + (i--));
145 while (simplify(const_fold, at_zero, in_lvalue, 2, width_hint, sign_hint, in_param)) { }
158 if ((type ==
AST_FCALL || type ==
AST_TCALL) && (str ==
"$display" || str ==
"$stop" || str ==
"$finish")) {
173 std::map<std::string, AstNode*> backup_scope;
179 std::map<std::string, AstNode*> this_wire_scope;
180 for (
size_t i = 0; i < children.size(); i++) {
183 if (this_wire_scope.count(node->
str) > 0) {
184 AstNode *first_node = this_wire_scope[node->
str];
186 goto wires_are_compatible;
188 goto wires_are_incompatible;
189 for (
size_t j = 0; j < node->
children.size(); j++) {
193 goto wires_are_incompatible;
195 goto wires_are_incompatible;
196 }
else if (*n1 != *n2)
197 goto wires_are_incompatible;
200 goto wires_are_incompatible;
202 goto wires_are_incompatible;
204 goto wires_are_incompatible;
205 wires_are_compatible:
211 first_node->
is_reg =
true;
215 if (first_node->
attributes.count(it.first) > 0)
217 first_node->
attributes[it.first] = it.second->clone();
219 children.erase(children.begin()+(i--));
220 did_something =
true;
223 wires_are_incompatible:
225 log_error(
"Incompatible re-declaration of wire %s at %s:%d.\n", node->
str.c_str(), filename.c_str(), linenum);
228 this_wire_scope[node->
str] = node;
236 for (
size_t i = 0; i < children.size(); i++) {
240 did_something =
true;
248 int backup_width_hint = width_hint;
249 bool backup_sign_hint = sign_hint;
251 bool detect_width_simple =
false;
252 bool child_0_is_self_determined =
false;
253 bool child_1_is_self_determined =
false;
254 bool child_2_is_self_determined =
false;
255 bool children_are_self_determined =
false;
256 bool reset_width_after_children =
false;
263 while (!children[0]->basic_prep && children[0]->simplify(
false,
false,
true, stage, -1,
false, in_param) ==
true)
264 did_something =
true;
265 while (!children[1]->basic_prep && children[1]->simplify(
false,
false,
false, stage, -1,
false, in_param) ==
true)
266 did_something =
true;
267 children[0]->detectSignWidth(backup_width_hint, backup_sign_hint);
268 children[1]->detectSignWidth(width_hint, sign_hint);
269 width_hint = std::max(width_hint, backup_width_hint);
270 child_0_is_self_determined =
true;
275 while (!children[0]->basic_prep && children[0]->simplify(
false,
false,
false, stage, -1,
false,
true) ==
true)
276 did_something =
true;
277 children[0]->detectSignWidth(width_hint, sign_hint);
278 if (children.size() > 1 && children[1]->type ==
AST_RANGE) {
279 while (!children[1]->basic_prep && children[1]->simplify(
false,
false,
false, stage, -1,
false,
true) ==
true)
280 did_something =
true;
281 if (!children[1]->range_valid)
282 log_error(
"Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
283 width_hint = std::max(width_hint, children[1]->range_left - children[1]->range_right + 1);
297 detect_width_simple =
true;
298 children_are_self_determined =
true;
313 detect_width_simple =
true;
321 detect_width_simple =
true;
322 child_1_is_self_determined =
true;
335 for (
auto child : children) {
336 while (!child->basic_prep && child->simplify(
false,
false, in_lvalue, stage, -1,
false, in_param) ==
true)
337 did_something =
true;
338 child->detectSignWidthWorker(width_hint, sign_hint);
340 reset_width_after_children =
true;
346 detect_width_simple =
true;
347 children_are_self_determined =
true;
351 detect_width_simple =
true;
352 child_0_is_self_determined =
true;
356 detect_width_simple =
true;
357 children_are_self_determined =
true;
365 if (detect_width_simple && width_hint < 0) {
367 while (children[0]->simplify(
true,
false, in_lvalue, stage, -1,
false,
true) ==
true)
368 did_something =
true;
369 for (
auto child : children)
370 while (!child->basic_prep && child->simplify(
false,
false, in_lvalue, stage, -1,
false, in_param) ==
true)
371 did_something =
true;
372 detectSignWidth(width_hint, sign_hint);
376 int width_hint_left, width_hint_right;
377 bool sign_hint_left, sign_hint_right;
378 bool found_real_left, found_real_right;
379 children[1]->detectSignWidth(width_hint_left, sign_hint_left, &found_real_left);
380 children[2]->detectSignWidth(width_hint_right, sign_hint_right, &found_real_right);
381 if (found_real_left || found_real_right) {
382 child_1_is_self_determined =
true;
383 child_2_is_self_determined =
true;
389 while (children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { }
390 if (children[0]->type ==
AST_CONSTANT && children[0]->bits_only_01()) {
391 std::vector<AstNode*> new_children;
392 new_children.push_back(children[0]);
393 for (
int i = 1; i <
GetSize(children); i++) {
398 goto keep_const_cond;
401 while (v->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { }
403 if (v->bits == children[0]->bits) {
404 while (i+1 <
GetSize(children))
405 delete children[++i];
406 goto keep_const_cond;
410 goto keep_const_cond;
414 new_children.push_back(child);
418 new_children.swap(children);
424 for (
size_t i = 0; i < children.size(); i++) {
425 bool did_something_here =
true;
436 while (did_something_here && i < children.size()) {
437 bool const_fold_here = const_fold, in_lvalue_here = in_lvalue;
438 int width_hint_here = width_hint;
439 bool sign_hint_here = sign_hint;
440 bool in_param_here = in_param;
442 const_fold_here =
true, in_param_here =
true;
444 const_fold_here =
true;
446 in_lvalue_here =
true;
453 if (i == 0 && child_0_is_self_determined)
454 width_hint_here = -1, sign_hint_here =
false;
455 if (i == 1 && child_1_is_self_determined)
456 width_hint_here = -1, sign_hint_here =
false;
457 if (i == 2 && child_2_is_self_determined)
458 width_hint_here = -1, sign_hint_here =
false;
459 if (children_are_self_determined)
460 width_hint_here = -1, sign_hint_here =
false;
461 did_something_here = children[i]->
simplify(const_fold_here, at_zero, in_lvalue_here, stage, width_hint_here, sign_hint_here, in_param_here);
462 if (did_something_here)
463 did_something =
true;
467 children.erase(children.begin() + (i--));
468 did_something =
true;
471 for (
auto &attr : attributes) {
472 while (attr.second->simplify(
true,
false,
false, stage, -1,
false,
true))
473 did_something =
true;
476 if (reset_width_after_children) {
477 width_hint = backup_width_hint;
478 sign_hint = backup_sign_hint;
480 detectSignWidth(width_hint, sign_hint);
487 for (
auto it = backup_scope.begin(); it != backup_scope.end(); it++) {
488 if (it->second ==
NULL)
502 size_t pos = str.rfind(
'.');
503 if (pos == std::string::npos)
504 log_error(
"Defparam `%s' does not contain a dot (module/parameter separator) at %s:%d!\n",
506 std::string modname = str.substr(0, pos), paraname =
"\\" + str.substr(pos+1);
512 paraset->str = paraname;
520 log_error(
"Index in generate block prefix syntax at %s:%d is not constant!\n", filename.c_str(), linenum);
523 newNode = children[1]->
clone();
524 const char *second_part = children[1]->
str.c_str();
525 if (second_part[0] ==
'\\')
527 newNode->
str =
stringf(
"%s[%d].%s", str.c_str(), children[0]->integer, second_part);
534 log_error(
"Left operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
536 log_error(
"Right operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
537 RTLIL::Const new_value = children[1]->bitsAsConst(children[0]->bitsAsConst().as_int(), children[1]->is_signed);
538 newNode = mkconst_bits(new_value.bits, children[1]->is_signed);
544 bool old_range_valid = range_valid;
546 range_swapped =
false;
552 range_left = children[0]->integer;
553 if (children.size() == 1)
554 range_right = range_left;
556 if (children.size() >= 2) {
558 range_right = children[1]->integer;
562 if (old_range_valid != range_valid)
563 did_something =
true;
564 if (range_valid && range_left >= 0 && range_right > range_left) {
565 int tmp = range_right;
566 range_right = range_left;
568 range_swapped =
true;
574 if (children.size() > 0) {
575 if (children[0]->range_valid) {
577 did_something =
true;
579 range_swapped = children[0]->range_swapped;
580 range_left = children[0]->range_left;
581 range_right = children[0]->range_right;
585 did_something =
true;
587 range_swapped =
false;
597 multirange_dimensions.clear();
598 for (
auto range : children[1]->children) {
599 if (!range->range_valid)
600 log_error(
"Non-constant range on memory decl at %s:%d.\n", filename.c_str(), linenum);
601 multirange_dimensions.push_back(std::min(range->range_left, range->range_right));
602 multirange_dimensions.push_back(std::max(range->range_left, range->range_right) - std::min(range->range_left, range->range_right) + 1);
603 total_size *= multirange_dimensions.back();
607 did_something =
true;
615 for (
int i = 0; 2*i <
GetSize(id2ast->multirange_dimensions); i++)
617 if (
GetSize(children[0]->children) < i)
618 log_error(
"Insufficient number of array indices for %s at %s:%d.\n",
log_id(str), filename.c_str(), linenum);
620 AstNode *new_index_expr = children[0]->
children[i]->children.at(0)->clone();
622 if (id2ast->multirange_dimensions[2*i])
626 index_expr = new_index_expr;
631 for (
int i =
GetSize(id2ast->multirange_dimensions)/1; i < GetSize(children[0]->children); i++)
632 children.push_back(children[0]->children[i]->clone());
635 if (index_expr ==
nullptr)
636 children.erase(children.begin());
640 did_something =
true;
645 if (children.size() > 1 && children[1]->type ==
AST_RANGE) {
646 if (!children[1]->range_valid)
647 log_error(
"Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
648 int width = children[1]->range_left - children[1]->range_right + 1;
650 RTLIL::Const constvalue = children[0]->realAsConst(width);
651 log_warning(
"converting real value %e to binary %s at %s:%d.\n",
652 children[0]->realvalue,
log_signal(constvalue), filename.c_str(), linenum);
654 children[0] = mkconst_bits(constvalue.
bits, sign_hint);
655 did_something =
true;
658 if (width !=
int(children[0]->bits.size())) {
660 sig.
extend_u0(width, children[0]->is_signed);
661 AstNode *old_child_0 = children[0];
662 children[0] = mkconst_bits(sig.
as_const().
bits, children[0]->is_signed);
668 range_swapped = children[1]->range_swapped;
669 range_left = children[1]->range_left;
670 range_right = children[1]->range_right;
673 double as_realvalue = children[0]->asReal(sign_hint);
676 children[0]->realvalue = as_realvalue;
677 did_something =
true;
695 auto_wire->
str = str;
698 did_something =
true;
702 did_something =
true;
709 if (id2ast ==
NULL || id2ast->type !=
AST_MEMORY || children[0]->children.size() != 1)
710 log_error(
"Invalid bit-select on memory access at %s:%d!\n", filename.c_str(), linenum);
712 int mem_width, mem_size, addr_bits;
713 id2ast->meminfo(mem_width, mem_size, addr_bits);
715 std::stringstream sstr;
716 sstr <<
"$mem2bits$" << children[0]->str <<
"$" << filename <<
":" << linenum <<
"$" << (
autoidx++);
717 std::string wire_id = sstr.str();
724 while (wire->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
735 size_t assign_idx = 0;
738 log_assert(assign_idx < current_block->children.size());
745 proc->
children[0]->children.push_back(assign);
750 newNode->
str = wire_id;
756 log_error(
"While loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum);
759 log_error(
"Repeat loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum);
764 AstNode *init_ast = children[0];
765 AstNode *while_ast = children[1];
766 AstNode *next_ast = children[2];
767 AstNode *body_ast = children[3];
771 body_ast = body_ast->
children.at(0);
774 log_error(
"Unsupported 1st expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
776 log_error(
"Unsupported 3rd expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
780 log_error(
"Left hand side of 1st expression of generate for-loop at %s:%d is not a gen var!\n", filename.c_str(), linenum);
782 log_error(
"Left hand side of 3rd expression of generate for-loop at %s:%d is not a gen var!\n", filename.c_str(), linenum);
785 log_error(
"Left hand side of 1st expression of generate for-loop at %s:%d is not a register!\n", filename.c_str(), linenum);
787 log_error(
"Left hand side of 3rd expression of generate for-loop at %s:%d is not a register!\n", filename.c_str(), linenum);
791 log_error(
"Incompatible left-hand sides in 1st and 3rd expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
795 while (varbuf->simplify(
true,
false,
false, stage, width_hint, sign_hint,
false)) { }
798 log_error(
"Right hand side of 1st expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
801 varbuf->str = init_ast->
children[0]->str;
806 size_t current_block_idx = 0;
808 while (current_block_idx < current_block->children.size() &&
817 while (buf->
simplify(
true,
false,
false, stage, width_hint, sign_hint,
false)) { }
820 log_error(
"2nd expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
829 int index = varbuf->
children[0]->integer;
831 buf = body_ast->
clone();
834 if (buf->
str.empty()) {
835 std::stringstream sstr;
836 sstr <<
"$genblock$" << filename <<
":" << linenum <<
"$" << (
autoidx++);
837 buf->
str = sstr.str();
839 std::map<std::string, std::string> name_map;
840 std::stringstream sstr;
841 sstr << buf->
str <<
"[" << index <<
"].";
845 for (
size_t i = 0; i < buf->
children.size(); i++) {
846 buf->
children[i]->simplify(
false,
false,
false, stage, -1,
false,
false);
850 for (
size_t i = 0; i < buf->
children.size(); i++)
857 buf = next_ast->
children[1]->clone();
858 while (buf->
simplify(
true,
false,
false, stage, width_hint, sign_hint,
false)) { }
861 log_error(
"Right hand side of 3rd expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
863 delete varbuf->children[0];
864 varbuf->children[0] = buf;
870 did_something =
true;
876 std::map<std::string, std::string> name_map;
877 expand_genblock(std::string(), str +
".", name_map);
879 std::vector<AstNode*> new_children;
880 for (
size_t i = 0; i < children.size(); i++)
881 if (children[i]->type ==
AST_WIRE) {
882 children[i]->simplify(
false,
false,
false, stage, -1,
false,
false);
886 new_children.push_back(children[i]);
888 children.swap(new_children);
889 did_something =
true;
897 std::map<std::string, std::string> name_map;
898 expand_genblock(std::string(), str +
".", name_map);
901 for (
size_t i = 0; i < children.size(); i++) {
902 children[i]->simplify(
false,
false,
false, stage, -1,
false,
false);
907 did_something =
true;
911 if (type ==
AST_GENIF && children.size() != 0)
914 while (buf->
simplify(
true,
false,
false, stage, width_hint, sign_hint,
false)) { }
918 log_error(
"Condition for generate if at %s:%d is not constant!\n", filename.c_str(), linenum);
922 buf = children[1]->
clone();
925 buf = children.size() > 2 ? children[2]->
clone() :
NULL;
933 if (!buf->
str.empty()) {
934 std::map<std::string, std::string> name_map;
938 for (
size_t i = 0; i < buf->
children.size(); i++) {
939 buf->
children[i]->simplify(
false,
false,
false, stage, -1,
false,
false);
948 did_something =
true;
955 while (buf->
simplify(
true,
false,
false, stage, width_hint, sign_hint,
false)) { }
959 log_error(
"Condition for generate case at %s:%d is not constant!\n", filename.c_str(), linenum);
967 for (
size_t i = 1; i < children.size(); i++)
972 for (
auto child : children.at(i)->children) {
975 this_genblock = child;
978 for (
auto child : children.at(i)->children)
981 if (selected_case ==
NULL)
982 selected_case = this_genblock;
988 buf = child->
clone();
989 while (buf->
simplify(
true,
false,
false, stage, width_hint, sign_hint,
false)) { }
993 log_error(
"Expression in generate case at %s:%d is not constant!\n", filename.c_str(), linenum);
1000 selected_case = this_genblock;
1001 i = children.size();
1007 if (selected_case !=
NULL)
1010 buf = selected_case->
clone();
1012 if (!buf->
str.empty()) {
1013 std::map<std::string, std::string> name_map;
1017 for (
size_t i = 0; i < buf->
children.size(); i++) {
1018 buf->
children[i]->simplify(
false,
false,
false, stage, -1,
false,
false);
1027 did_something =
true;
1033 if (!children.at(0)->range_valid)
1034 log_error(
"Non-constant array range on cell array at %s:%d.\n", filename.c_str(), linenum);
1037 int num = std::max(children.at(0)->range_left, children.at(0)->range_right) - std::min(children.at(0)->range_left, children.at(0)->range_right) + 1;
1039 for (
int i = 0; i < num; i++) {
1040 int idx = children.at(0)->range_left > children.at(0)->range_right ? children.at(0)->range_right + i : children.at(0)->range_right - i;
1042 newNode->
children.push_back(new_cell);
1045 log_error(
"Cell arrays of primitives are currently not supported at %s:%d.\n", filename.c_str(), linenum);
1058 if (children.size() < 2)
1059 log_error(
"Insufficient number of arguments for primitive `%s' at %s:%d!\n",
1060 str.c_str(), filename.c_str(), linenum);
1062 std::vector<AstNode*> children_list;
1063 for (
auto child : children) {
1066 children_list.push_back(child->children[0]);
1067 child->children.clear();
1072 if (str ==
"bufif0" || str ==
"bufif1" || str ==
"notif0" || str ==
"notif1")
1074 if (children_list.size() != 3)
1075 log_error(
"Invalid number of arguments for primitive `%s' at %s:%d!\n",
1076 str.c_str(), filename.c_str(), linenum);
1080 AstNode *mux_input = children_list.at(1);
1081 if (str ==
"notif0" || str ==
"notif1") {
1085 if (str ==
"bufif0") {
1087 node->
children.push_back(mux_input);
1089 node->
children.push_back(mux_input);
1095 children.push_back(children_list.at(0));
1096 children.push_back(node);
1097 did_something =
true;
1102 bool invert_results =
false;
1119 op_type =
AST_POS, invert_results =
true;
1122 AstNode *node = children_list[1];
1124 for (
size_t i = 2; i < children_list.size(); i++)
1125 node =
new AstNode(op_type, node, children_list[i]);
1131 children.push_back(children_list[0]);
1132 children.push_back(node);
1133 did_something =
true;
1140 if (children[0]->type !=
AST_IDENTIFIER || children[0]->children.size() == 0)
1141 goto skip_dynamic_range_lvalue_expansion;
1142 if (children[0]->children[0]->range_valid || did_something)
1143 goto skip_dynamic_range_lvalue_expansion;
1144 if (children[0]->id2ast ==
NULL || children[0]->id2ast->type !=
AST_WIRE)
1145 goto skip_dynamic_range_lvalue_expansion;
1146 if (!children[0]->id2ast->range_valid)
1147 goto skip_dynamic_range_lvalue_expansion;
1148 int source_width = children[0]->id2ast->range_left - children[0]->id2ast->range_right + 1;
1149 int result_width = 1;
1153 shift_expr = range->
children[0]->clone();
1155 shift_expr = range->
children[1]->clone();
1158 while (left_at_zero_ast->
simplify(
true,
true,
false, stage, -1,
false,
false)) { }
1159 while (right_at_zero_ast->
simplify(
true,
true,
false, stage, -1,
false,
false)) { }
1161 log_error(
"Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
1162 str.c_str(), filename.c_str(), linenum);
1163 result_width = abs(
int(left_at_zero_ast->
integer - right_at_zero_ast->
integer)) + 1;
1165 did_something =
true;
1167 for (
int i = 0; i <= source_width-result_width; i++) {
1168 int start_bit = children[0]->id2ast->range_right + i;
1173 mkconst_int(start_bit+result_width-1,
true), mkconst_int(start_bit,
true)));
1179 skip_dynamic_range_lvalue_expansion:;
1183 std::stringstream sstr;
1184 sstr <<
"$assert$" << filename <<
":" << linenum <<
"$" << (
autoidx++);
1185 std::string id_check = sstr.str() +
"_CHECK", id_en = sstr.str() +
"_EN";
1188 wire_check->
str = id_check;
1191 while (wire_check->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
1194 wire_en->
str = id_en;
1199 while (wire_en->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
1201 std::vector<RTLIL::State> x_bit;
1205 assign_check->
children[0]->str = id_check;
1208 assign_en->
children[0]->str = id_en;
1211 default_signals->
children.push_back(assign_check);
1212 default_signals->
children.push_back(assign_en);
1216 assign_check->
children[0]->str = id_check;
1219 assign_en->
children[0]->str = id_en;
1222 newNode->
children.push_back(assign_check);
1223 newNode->
children.push_back(assign_en);
1228 assertnode->
children[0]->str = id_check;
1229 assertnode->
children[1]->str = id_en;
1236 if (stage > 1 && type ==
AST_ASSERT && children.size() == 1)
1239 children.push_back(mkconst_int(1,
false, 1));
1240 did_something =
true;
1245 children[0]->type ==
AST_RANGE && children[0]->children.size() == 1) {
1248 newNode->
id2ast = id2ast;
1254 children[0]->id2ast && children[0]->id2ast->type ==
AST_MEMORY && children[0]->id2ast->children.size() >= 2 &&
1255 children[0]->id2ast->children[0]->range_valid && children[0]->id2ast->children[1]->range_valid &&
1256 (children[0]->children.size() == 1 || children[0]->children.size() == 2) && children[0]->children[0]->type ==
AST_RANGE)
1258 std::stringstream sstr;
1259 sstr <<
"$memwr$" << children[0]->
str <<
"$" << filename <<
":" << linenum <<
"$" << (
autoidx++);
1260 std::string id_addr = sstr.str() +
"_ADDR", id_data = sstr.str() +
"_DATA", id_en = sstr.str() +
"_EN";
1263 log_warning(
"Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n",
1264 filename.c_str(), linenum);
1266 int mem_width, mem_size, addr_bits;
1267 children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
1270 wire_addr->
str = id_addr;
1273 while (wire_addr->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
1276 wire_data->
str = id_data;
1279 while (wire_data->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
1282 wire_en->
str = id_en;
1285 while (wire_en->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
1287 std::vector<RTLIL::State> x_bits_addr, x_bits_data, set_bits_en;
1288 for (
int i = 0; i < addr_bits; i++)
1290 for (
int i = 0; i < mem_width; i++)
1292 for (
int i = 0; i < mem_width; i++)
1296 assign_addr->
children[0]->str = id_addr;
1299 assign_data->
children[0]->str = id_data;
1302 assign_en->
children[0]->str = id_en;
1305 default_signals->
children.push_back(assign_addr);
1306 default_signals->
children.push_back(assign_data);
1307 default_signals->
children.push_back(assign_en);
1311 assign_addr->
children[0]->str = id_addr;
1313 if (children[0]->children.size() == 2)
1315 if (children[0]->children[1]->range_valid)
1317 int offset = children[0]->children[1]->range_right;
1318 int width = children[0]->children[1]->range_left - offset + 1;
1322 for (
int i = 0; i < mem_width; i++)
1327 assign_data->
children[0]->str = id_data;
1330 assign_en->
children[0]->str = id_en;
1339 while (left_at_zero_ast->
simplify(
true,
true,
false, 1, -1,
false,
false)) { }
1340 while (right_at_zero_ast->
simplify(
true,
true,
false, 1, -1,
false,
false)) { }
1342 log_error(
"Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
1343 int width = left_at_zero_ast->
integer - right_at_zero_ast->
integer + 1;
1345 for (
int i = 0; i < mem_width; i++)
1350 assign_data->
children[0]->str = id_data;
1354 assign_en->
children[0]->str = id_en;
1356 delete left_at_zero_ast;
1357 delete right_at_zero_ast;
1364 assign_data->
children[0]->str = id_data;
1367 assign_en->
children[0]->str = id_en;
1371 newNode->
children.push_back(assign_addr);
1372 newNode->
children.push_back(assign_data);
1373 newNode->
children.push_back(assign_en);
1379 wrnode->
str = children[0]->str;
1380 wrnode->
children[0]->str = id_addr;
1381 wrnode->
children[1]->str = id_data;
1393 if (str ==
"\\$clog2")
1395 if (children.size() != 1)
1396 log_error(
"System function %s got %d arguments, expected 1 at %s:%d.\n",
1400 while (buf->
simplify(
true,
false,
false, stage, width_hint, sign_hint,
false)) { }
1402 log_error(
"Failed to evaluate system function `%s' with non-constant value at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1405 if (arg_value.as_bool())
1409 uint32_t result = 0;
1410 for (
size_t i = 0; i < arg_value.bits.size(); i++)
1414 newNode = mkconst_int(result,
false);
1418 if (str ==
"\\$ln" || str ==
"\\$log10" || str ==
"\\$exp" || str ==
"\\$sqrt" || str ==
"\\$pow" ||
1419 str ==
"\\$floor" || str ==
"\\$ceil" || str ==
"\\$sin" || str ==
"\\$cos" || str ==
"\\$tan" ||
1420 str ==
"\\$asin" || str ==
"\\$acos" || str ==
"\\$atan" || str ==
"\\$atan2" || str ==
"\\$hypot" ||
1421 str ==
"\\$sinh" || str ==
"\\$cosh" || str ==
"\\$tanh" || str ==
"\\$asinh" || str ==
"\\$acosh" || str ==
"\\$atanh")
1423 bool func_with_two_arguments = str ==
"\\$pow" || str ==
"\\$atan2" || str ==
"\\$hypot";
1424 double x = 0, y = 0;
1426 if (func_with_two_arguments) {
1427 if (children.size() != 2)
1428 log_error(
"System function %s got %d arguments, expected 2 at %s:%d.\n",
1431 if (children.size() != 1)
1432 log_error(
"System function %s got %d arguments, expected 1 at %s:%d.\n",
1436 if (children.size() >= 1) {
1437 while (children[0]->simplify(
true,
false,
false, stage, width_hint, sign_hint,
false)) { }
1438 if (!children[0]->isConst())
1439 log_error(
"Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
1441 int child_width_hint = width_hint;
1442 bool child_sign_hint = sign_hint;
1443 children[0]->detectSignWidth(child_width_hint, child_sign_hint);
1444 x = children[0]->asReal(child_sign_hint);
1447 if (children.size() >= 2) {
1448 while (children[1]->simplify(
true,
false,
false, stage, width_hint, sign_hint,
false)) { }
1449 if (!children[1]->isConst())
1450 log_error(
"Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
1452 int child_width_hint = width_hint;
1453 bool child_sign_hint = sign_hint;
1454 children[1]->detectSignWidth(child_width_hint, child_sign_hint);
1455 y = children[1]->asReal(child_sign_hint);
1460 else if (str ==
"\\$log10") newNode->
realvalue = ::log10(x);
1461 else if (str ==
"\\$exp") newNode->
realvalue = ::exp(x);
1462 else if (str ==
"\\$sqrt") newNode->
realvalue = ::sqrt(x);
1463 else if (str ==
"\\$pow") newNode->
realvalue = ::pow(x, y);
1464 else if (str ==
"\\$floor") newNode->
realvalue = ::floor(x);
1465 else if (str ==
"\\$ceil") newNode->
realvalue = ::ceil(x);
1466 else if (str ==
"\\$sin") newNode->
realvalue = ::sin(x);
1467 else if (str ==
"\\$cos") newNode->
realvalue = ::cos(x);
1468 else if (str ==
"\\$tan") newNode->
realvalue = ::tan(x);
1469 else if (str ==
"\\$asin") newNode->
realvalue = ::asin(x);
1470 else if (str ==
"\\$acos") newNode->
realvalue = ::acos(x);
1471 else if (str ==
"\\$atan") newNode->
realvalue = ::atan(x);
1472 else if (str ==
"\\$atan2") newNode->
realvalue = ::atan2(x, y);
1473 else if (str ==
"\\$hypot") newNode->
realvalue = ::hypot(x, y);
1474 else if (str ==
"\\$sinh") newNode->
realvalue = ::sinh(x);
1475 else if (str ==
"\\$cosh") newNode->
realvalue = ::cosh(x);
1476 else if (str ==
"\\$tanh") newNode->
realvalue = ::tanh(x);
1477 else if (str ==
"\\$asinh") newNode->
realvalue = ::asinh(x);
1478 else if (str ==
"\\$acosh") newNode->
realvalue = ::acosh(x);
1479 else if (str ==
"\\$atanh") newNode->
realvalue = ::atanh(x);
1488 std::string rtype, fname;
1489 std::vector<std::string> argtypes;
1490 std::vector<AstNode*>
args;
1498 log_error(
"Insufficient number of arguments in DPI function call at %s:%d.\n", filename.c_str(), linenum);
1501 args.push_back(children.at(i-2)->clone());
1502 while (args.back()->simplify(
true,
false,
false, stage, -1,
false,
true)) { }
1505 log_error(
"Failed to evaluate DPI function with non-constant argument at %s:%d.\n", filename.c_str(), linenum);
1508 newNode =
dpi_call(rtype, fname, argtypes, args);
1510 for (
auto arg : args)
1517 log_error(
"Can't resolve function name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1520 if (str ==
"\\$readmemh" || str ==
"\\$readmemb")
1523 log_error(
"System function %s got %d arguments, expected 2-4 at %s:%d.\n",
1527 while (node_filename->
simplify(
true,
false,
false, stage, width_hint, sign_hint,
false)) { }
1529 log_error(
"Failed to evaluate system function `%s' with non-constant 1st argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1532 while (node_memory->simplify(
true,
false,
false, stage, width_hint, sign_hint,
false)) { }
1533 if (node_memory->type !=
AST_IDENTIFIER || node_memory->id2ast ==
nullptr || node_memory->id2ast->type !=
AST_MEMORY)
1534 log_error(
"Failed to evaluate system function `%s' with non-memory 2nd argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1536 int start_addr = -1, finish_addr = -1;
1540 while (node_addr->
simplify(
true,
false,
false, stage, width_hint, sign_hint,
false)) { }
1542 log_error(
"Failed to evaluate system function `%s' with non-constant 3rd argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1543 start_addr = node_addr->
asInt(
false);
1548 while (node_addr->
simplify(
true,
false,
false, stage, width_hint, sign_hint,
false)) { }
1550 log_error(
"Failed to evaluate system function `%s' with non-constant 4th argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1551 finish_addr = node_addr->
asInt(
false);
1554 newNode = readmem(str ==
"\\$readmemh", node_filename->
bitsAsConst().
decode_string(), node_memory->id2ast, start_addr, finish_addr);
1559 log_error(
"Can't resolve task name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1564 std::stringstream sstr;
1565 sstr <<
"$func$" << str <<
"$" << filename <<
":" << linenum <<
"$" << (
autoidx++) <<
"$";
1566 std::string prefix = sstr.str();
1568 bool recommend_const_eval =
false;
1569 bool require_const_eval = in_param ?
false : has_const_only_constructs(recommend_const_eval);
1570 if ((in_param || recommend_const_eval || require_const_eval) && !decl->
attributes.count(
"\\via_celltype"))
1572 bool all_args_const =
true;
1573 for (
auto child : children) {
1574 while (child->simplify(
true,
false,
false, 1, -1,
false,
true)) { }
1576 all_args_const =
false;
1579 if (all_args_const) {
1582 delete func_workspace;
1587 log_error(
"Non-constant function call in constant expression at %s:%d.\n", filename.c_str(), linenum);
1588 if (require_const_eval)
1589 log_error(
"Function %s can only be called with constant arguments at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1592 size_t arg_count = 0;
1593 std::map<std::string, std::string> replace_rules;
1601 if (child->type ==
AST_WIRE && child->str == str)
1602 wire = child->
clone();
1605 wire->
str = prefix + str;
1611 while (wire->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
1620 goto replace_fcall_with_id;
1623 if (decl->
attributes.count(
"\\via_celltype"))
1625 std::string celltype = decl->
attributes.at(
"\\via_celltype")->asAttrConst().decode_string();
1626 std::string outport = str;
1628 if (celltype.find(
' ') != std::string::npos) {
1629 int pos = celltype.find(
' ');
1636 cell->
str = prefix.substr(0,
GetSize(prefix)-1);
1640 if (attr.first.str().rfind(
"\\via_celltype_defparam_", 0) == 0)
1643 cell_arg->
str =
RTLIL::escape_id(attr.first.str().substr(strlen(
"\\via_celltype_defparam_")));
1644 cell->
children.push_back(cell_arg);
1648 if (child->type ==
AST_WIRE && (child->is_input || child->is_output || (type ==
AST_FCALL && child->str == str)))
1651 wire->
str = prefix + wire->
str;
1656 while (wire->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
1659 wire_id->
str = wire->
str;
1661 if ((child->is_input || child->is_output) && arg_count < children.size())
1677 cell_arg->
str = child->str == str ? outport : child->str;
1678 cell->
children.push_back(cell_arg);
1682 goto replace_fcall_with_id;
1689 wire->
str = prefix + wire->
str;
1694 while (wire->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
1696 replace_rules[child->str] = wire->
str;
1698 if ((child->is_input || child->is_output) && arg_count < children.size())
1702 wire_id->
str = wire->
str;
1730 replace_fcall_with_id:
1738 did_something =
true;
1745 std::vector<RTLIL::State> tmp_bits;
1747 RTLIL::Const dummy_arg;
1754 if (children.size() != 0 && children[0]->type ==
AST_RANGE && children[0]->range_valid) {
1755 std::vector<RTLIL::State> data;
1760 int tmp_range_left = children[0]->range_left, tmp_range_right = children[0]->range_right;
1762 tmp_range_left = (param_width + 2*param_offset) - children[0]->range_right - 1;
1763 tmp_range_right = (param_width + 2*param_offset) - children[0]->range_left - 1;
1765 for (
int i = tmp_range_right; i <= tmp_range_left; i++) {
1766 int index = i - param_offset;
1767 if (0 <= index && index < param_width)
1768 data.push_back(
current_scope[str]->children[0]->bits[index]);
1772 newNode = mkconst_bits(data,
false);
1774 if (children.size() == 0)
1781 newNode = mkconst_int(0, sign_hint, width_hint);
1786 RTLIL::Const y =
RTLIL::const_not(children[0]->bitsAsConst(width_hint, sign_hint), dummy_arg, sign_hint,
false, width_hint);
1787 newNode = mkconst_bits(y.
bits, sign_hint);
1793 RTLIL::Const y = children[0]->bitsAsConst(width_hint, sign_hint);
1802 RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
1803 children[1]->bitsAsConst(width_hint, sign_hint), sign_hint, sign_hint, width_hint);
1804 newNode = mkconst_bits(y.
bits, sign_hint);
1813 RTLIL::Const y = const_func(RTLIL::Const(children[0]->bits), dummy_arg,
false,
false, -1);
1814 newNode = mkconst_bits(y.
bits,
false);
1819 RTLIL::Const y =
RTLIL::const_logic_not(RTLIL::Const(children[0]->bits), dummy_arg, children[0]->is_signed,
false, -1);
1820 newNode = mkconst_bits(y.
bits,
false);
1822 if (children[0]->isConst()) {
1823 newNode = mkconst_int(children[0]->asReal(sign_hint) == 0,
false, 1);
1829 RTLIL::Const y = const_func(RTLIL::Const(children[0]->bits), RTLIL::Const(children[1]->bits),
1830 children[0]->is_signed, children[1]->is_signed, -1);
1831 newNode = mkconst_bits(y.
bits,
false);
1833 if (children[0]->isConst() && children[1]->isConst()) {
1835 newNode = mkconst_int((children[0]->asReal(sign_hint) != 0) && (children[1]->asReal(sign_hint) != 0),
false, 1);
1837 newNode = mkconst_int((children[0]->asReal(sign_hint) != 0) || (children[1]->asReal(sign_hint) != 0),
false, 1);
1846 RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
1847 RTLIL::Const(children[1]->bits), sign_hint, type ==
AST_POW ? children[1]->is_signed :
false, width_hint);
1848 newNode = mkconst_bits(y.
bits, sign_hint);
1850 if (type ==
AST_POW && children[0]->isConst() && children[1]->isConst()) {
1852 newNode->
realvalue = pow(children[0]->asReal(sign_hint), children[1]->asReal(sign_hint));
1864 int cmp_width = std::max(children[0]->bits.size(), children[1]->bits.size());
1865 bool cmp_signed = children[0]->is_signed && children[1]->is_signed;
1866 RTLIL::Const y = const_func(children[0]->bitsAsConst(cmp_width, cmp_signed),
1867 children[1]->bitsAsConst(cmp_width, cmp_signed), cmp_signed, cmp_signed, 1);
1868 newNode = mkconst_bits(y.
bits,
false);
1870 if (children[0]->isConst() && children[1]->isConst()) {
1871 bool cmp_signed = (children[0]->type ==
AST_REALVALUE || children[0]->is_signed) && (children[1]->type ==
AST_REALVALUE || children[1]->is_signed);
1873 case AST_LT: newNode = mkconst_int(children[0]->asReal(cmp_signed) < children[1]->asReal(cmp_signed),
false, 1);
break;
1874 case AST_LE: newNode = mkconst_int(children[0]->asReal(cmp_signed) <= children[1]->asReal(cmp_signed),
false, 1);
break;
1875 case AST_EQ: newNode = mkconst_int(children[0]->asReal(cmp_signed) == children[1]->asReal(cmp_signed),
false, 1);
break;
1876 case AST_NE: newNode = mkconst_int(children[0]->asReal(cmp_signed) != children[1]->asReal(cmp_signed),
false, 1);
break;
1877 case AST_EQX: newNode = mkconst_int(children[0]->asReal(cmp_signed) == children[1]->asReal(cmp_signed),
false, 1);
break;
1878 case AST_NEX: newNode = mkconst_int(children[0]->asReal(cmp_signed) != children[1]->asReal(cmp_signed),
false, 1);
break;
1879 case AST_GE: newNode = mkconst_int(children[0]->asReal(cmp_signed) >= children[1]->asReal(cmp_signed),
false, 1);
break;
1880 case AST_GT: newNode = mkconst_int(children[0]->asReal(cmp_signed) > children[1]->asReal(cmp_signed),
false, 1);
break;
1891 RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
1892 children[1]->bitsAsConst(width_hint, sign_hint), sign_hint, sign_hint, width_hint);
1893 newNode = mkconst_bits(y.
bits, sign_hint);
1895 if (children[0]->isConst() && children[1]->isConst()) {
1898 case AST_ADD: newNode->
realvalue = children[0]->asReal(sign_hint) + children[1]->asReal(sign_hint);
break;
1899 case AST_SUB: newNode->
realvalue = children[0]->asReal(sign_hint) - children[1]->asReal(sign_hint);
break;
1900 case AST_MUL: newNode->
realvalue = children[0]->asReal(sign_hint) * children[1]->asReal(sign_hint);
break;
1901 case AST_DIV: newNode->
realvalue = children[0]->asReal(sign_hint) / children[1]->asReal(sign_hint);
break;
1902 case AST_MOD: newNode->
realvalue = fmod(children[0]->asReal(sign_hint), children[1]->asReal(sign_hint));
break;
1910 RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint), dummy_arg, sign_hint,
false, width_hint);
1911 newNode = mkconst_bits(y.
bits, sign_hint);
1913 if (children[0]->isConst()) {
1916 newNode->
realvalue = +children[0]->asReal(sign_hint);
1918 newNode->
realvalue = -children[0]->asReal(sign_hint);
1922 if (children[0]->isConst())
1924 bool found_sure_true =
false;
1925 bool found_maybe_true =
false;
1928 for (
auto &bit : children[0]->bits) {
1930 found_sure_true =
true;
1932 found_maybe_true =
true;
1935 found_sure_true = children[0]->asReal(sign_hint) != 0;
1938 if (found_sure_true)
1939 choice = children[1], not_choice = children[2];
1940 else if (!found_maybe_true)
1941 choice = children[2], not_choice = children[1];
1943 if (choice !=
NULL) {
1945 int other_width_hint = width_hint;
1946 bool other_sign_hint = sign_hint, other_real =
false;
1947 not_choice->
detectSignWidth(other_width_hint, other_sign_hint, &other_real);
1953 RTLIL::Const y = choice->
bitsAsConst(width_hint, sign_hint);
1954 if (choice->
is_string && y.
bits.size() % 8 == 0 && sign_hint ==
false)
1955 newNode = mkconst_str(y.
bits);
1957 newNode = mkconst_bits(y.
bits, sign_hint);
1961 newNode = choice->
clone();
1964 RTLIL::Const a = children[1]->bitsAsConst(width_hint, sign_hint);
1965 RTLIL::Const b = children[2]->bitsAsConst(width_hint, sign_hint);
1967 for (
size_t i = 0; i < a.
bits.size(); i++)
1970 newNode = mkconst_bits(a.
bits, sign_hint);
1971 }
else if (children[1]->isConst() && children[2]->isConst()) {
1973 if (children[1]->asReal(sign_hint) == children[2]->asReal(sign_hint))
1974 newNode->
realvalue = children[1]->asReal(sign_hint);
1984 string_op = !children.empty();
1985 for (
auto it = children.begin(); it != children.end(); it++) {
1988 if (!(*it)->is_string)
1990 tmp_bits.insert(tmp_bits.end(), (*it)->bits.begin(), (*it)->bits.end());
1992 newNode = string_op ? mkconst_str(tmp_bits) : mkconst_bits(tmp_bits,
false);
1997 for (
int i = 0; i < children[0]->bitsAsConst().as_int(); i++)
1998 tmp_bits.insert(tmp_bits.end(), children.at(1)->bits.begin(), children.at(1)->bits.end());
1999 newNode = children.at(1)->
is_string ? mkconst_str(tmp_bits) : mkconst_bits(tmp_bits,
false);
2018 did_something =
true;
2031 if (node->
str == from)
2041 f.open(mem_filename.c_str());
2044 log_error(
"Can not open file `%s` for %s at %s:%d.\n", mem_filename.c_str(), str.c_str(), filename.c_str(), linenum);
2047 int range_left = memory->
children[1]->range_left, range_right = memory->
children[1]->range_right;
2048 int range_min = std::min(range_left, range_right), range_max = std::max(range_left, range_right);
2051 start_addr = range_min;
2053 if (finish_addr < 0)
2054 finish_addr = range_max;
2056 bool in_comment =
false;
2057 int increment = start_addr <= finish_addr ? +1 : -1;
2058 int cursor = start_addr;
2062 std::string
line, token;
2063 std::getline(f, line);
2065 for (
int i = 0; i <
GetSize(line); i++) {
2066 if (in_comment && line.substr(i, 2) ==
"*/") {
2072 if (!in_comment && line.substr(i, 2) ==
"/*")
2081 if (token.empty() || token.substr(0, 2) ==
"//")
2084 if (token[0] ==
'@') {
2085 token = token.substr(1);
2086 const char *nptr = token.c_str();
2088 cursor = strtol(nptr, &endptr, 16);
2089 if (!*nptr || *endptr)
2090 log_error(
"Can not parse address `%s` for %s at %s:%d.\n", nptr, str.c_str(), filename.c_str(), linenum);
2097 block->
children.back()->children[0]->str = memory->
str;
2098 block->
children.back()->children[0]->id2ast = memory;
2100 if ((cursor == finish_addr) || (increment > 0 && cursor >= range_max) || (increment < 0 && cursor <= range_min))
2102 cursor += increment;
2105 if ((cursor == finish_addr) || (increment > 0 && cursor >= range_max) || (increment < 0 && cursor <= range_min))
2115 if (!index_var.empty() && type ==
AST_IDENTIFIER && str == index_var) {
2121 str = name_map[str];
2123 std::map<std::string, std::string> backup_name_map;
2125 for (
size_t i = 0; i < children.size(); i++) {
2129 if (backup_name_map.size() == 0)
2130 backup_name_map = name_map;
2131 std::string new_name = prefix[0] ==
'\\' ? prefix.substr(1) : prefix;
2132 size_t pos = child->
str.rfind(
'.');
2133 if (pos == std::string::npos)
2134 pos = child->
str[0] ==
'\\' ? 1 : 0;
2137 new_name = child->
str.substr(0, pos) + new_name + child->
str.substr(pos);
2138 if (new_name[0] !=
'$' && new_name[0] !=
'\\')
2139 new_name = prefix[0] + new_name;
2140 name_map[child->
str] = new_name;
2144 child->
str = new_name;
2149 for (
size_t i = 0; i < children.size(); i++) {
2155 if (backup_name_map.size() > 0)
2156 name_map.swap(backup_name_map);
2164 std::map<std::string, std::string> new_rules = rules;
2165 std::string new_prefix = prefix + str;
2167 for (
auto child : children)
2169 new_rules[child->str] = new_prefix + child->str;
2170 child->str = new_prefix + child->str;
2173 for (
auto child : children)
2175 child->replace_ids(new_prefix, new_rules);
2180 str = rules.at(str);
2181 for (
auto child : children)
2182 child->replace_ids(prefix, rules);
2188 std::map<AstNode*, uint32_t> &mem2reg_candidates,
AstNode *that)
2203 std::map<AstNode*, uint32_t> &mem2reg_candidates, std::map<AstNode*, uint32_t> &proc_flags, uint32_t &flags)
2205 uint32_t children_flags = 0;
2206 int ignore_children_counter = 0;
2211 for (
auto &lhs_child : children[0]->children)
2221 mem2reg_places[mem].insert(
stringf(
"%s:%d", filename.c_str(), linenum));
2228 mem2reg_places[mem].insert(
stringf(
"%s:%d", filename.c_str(), linenum));
2233 if (flags & MEM2REG_FL_INIT) {
2235 mem2reg_places[mem].insert(
stringf(
"%s:%d", filename.c_str(), linenum));
2239 mem2reg_places[mem].insert(
stringf(
"%s:%d", filename.c_str(), linenum));
2244 ignore_children_counter = 1;
2253 mem2reg_places[mem].insert(
stringf(
"%s:%d", filename.c_str(), linenum));
2262 if (type ==
AST_MODULE && get_bool_attribute(
"\\mem2reg"))
2265 std::map<AstNode*, uint32_t> *proc_flags_p =
NULL;
2268 int count_edge_events = 0;
2269 for (
auto child : children)
2271 count_edge_events++;
2272 if (count_edge_events != 1)
2274 proc_flags_p =
new std::map<AstNode*, uint32_t>;
2279 proc_flags_p =
new std::map<AstNode*, uint32_t>;
2282 uint32_t backup_flags = flags;
2283 flags |= children_flags;
2286 for (
auto child : children)
2287 if (ignore_children_counter > 0)
2288 ignore_children_counter--;
2289 else if (proc_flags_p)
2290 child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags);
2292 child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags);
2294 flags &= ~children_flags | backup_flags;
2297 for (
auto it : *proc_flags_p)
2299 delete proc_flags_p;
2305 if (type !=
AST_IDENTIFIER || !id2ast || !mem2reg_set.count(id2ast))
2308 if (children.empty() || children[0]->type !=
AST_RANGE ||
GetSize(children[0]->children) != 1)
2309 log_error(
"Invalid array access at %s:%d.\n", filename.c_str(), linenum);
2321 children[0]->mem2reg_check(mem2reg_set) && children[0]->children[0]->children[0]->type !=
AST_CONSTANT)
2323 std::stringstream sstr;
2324 sstr <<
"$mem2reg_wr$" << children[0]->
str <<
"$" << filename <<
":" << linenum <<
"$" << (
autoidx++);
2325 std::string id_addr = sstr.str() +
"_ADDR", id_data = sstr.str() +
"_DATA";
2327 int mem_width, mem_size, addr_bits;
2328 children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
2331 wire_addr->
str = id_addr;
2332 wire_addr->
is_reg =
true;
2334 mod->
children.push_back(wire_addr);
2335 while (wire_addr->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
2338 wire_data->
str = id_data;
2339 wire_data->
is_reg =
true;
2341 mod->
children.push_back(wire_data);
2342 while (wire_data->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
2345 size_t assign_idx = 0;
2346 while (assign_idx < block->children.size() && block->
children[assign_idx] !=
this)
2348 log_assert(assign_idx < block->children.size());
2351 assign_addr->children[0]->str = id_addr;
2355 case_node->
children[0]->str = id_addr;
2356 for (
int i = 0; i < mem_size; i++) {
2357 if (children[0]->children[0]->children[0]->type ==
AST_CONSTANT &&
int(children[0]->children[0]->children[0]->integer) != i)
2361 if (children[0]->children.size() == 2)
2362 assign_reg->
children[0]->children.push_back(children[0]->children[1]->clone());
2363 assign_reg->
children[0]->str =
stringf(
"%s[%d]", children[0]->str.c_str(), i);
2364 assign_reg->
children[1]->str = id_data;
2365 cond_node->
children[1]->children.push_back(assign_reg);
2366 case_node->
children.push_back(cond_node);
2370 children[0]->delete_children();
2371 children[0]->range_valid =
false;
2372 children[0]->id2ast =
NULL;
2373 children[0]->str = id_data;
2377 if (mem2reg_check(mem2reg_set))
2380 if (children.size() == 2)
2381 bit_part_sel = children[1]->clone();
2385 int id = children[0]->
children[0]->integer;
2386 str =
stringf(
"%s[%d]", str.c_str(),
id);
2389 range_valid =
false;
2394 std::stringstream sstr;
2395 sstr <<
"$mem2reg_rd$" << children[0]->str <<
"$" << filename <<
":" << linenum <<
"$" << (
autoidx++);
2396 std::string id_addr = sstr.str() +
"_ADDR", id_data = sstr.str() +
"_DATA";
2398 int mem_width, mem_size, addr_bits;
2399 id2ast->meminfo(mem_width, mem_size, addr_bits);
2402 wire_addr->
str = id_addr;
2403 wire_addr->
is_reg =
true;
2406 mod->
children.push_back(wire_addr);
2407 while (wire_addr->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
2410 wire_data->
str = id_data;
2411 wire_data->
is_reg =
true;
2414 mod->
children.push_back(wire_data);
2415 while (wire_data->
simplify(
true,
false,
false, 1, -1,
false,
false)) { }
2418 assign_addr->
children[0]->str = id_addr;
2421 case_node->
children[0]->str = id_addr;
2423 for (
int i = 0; i < mem_size; i++) {
2424 if (children[0]->children[0]->type ==
AST_CONSTANT &&
int(children[0]->children[0]->integer) != i)
2428 assign_reg->
children[0]->str = id_data;
2430 cond_node->
children[1]->children.push_back(assign_reg);
2431 case_node->
children.push_back(cond_node);
2434 std::vector<RTLIL::State> x_bits;
2435 for (
int i = 0; i < mem_width; i++)
2440 assign_reg->
children[0]->str = id_data;
2441 cond_node->
children[1]->children.push_back(assign_reg);
2442 case_node->
children.push_back(cond_node);
2446 size_t assign_idx = 0;
2447 while (assign_idx < block->children.size() && !block->
children[assign_idx]->contains(
this))
2449 log_assert(assign_idx < block->children.size());
2456 proc->
children[0]->children.push_back(case_node);
2458 mod->
children.push_back(assign_addr);
2462 range_valid =
false;
2468 children.push_back(bit_part_sel);
2473 auto children_list = children;
2474 for (
size_t i = 0; i < children_list.size(); i++)
2475 children_list[i]->mem2reg_as_needed_pass2(mem2reg_set, mod, block);
2483 mem_width = children[0]->range_left - children[0]->range_right + 1;
2484 mem_size = children[1]->range_left - children[1]->range_right;
2488 mem_size += std::min(children[1]->range_left, children[1]->range_right) + 1;
2491 while ((1 << addr_bits) < mem_size)
2498 recommend_const_eval =
true;
2502 if (
current_scope[str]->has_const_only_constructs(recommend_const_eval))
2504 for (
auto child : children)
2505 if (child->AstNode::has_const_only_constructs(recommend_const_eval))
2514 int offset = variables.at(str).offset, width = variables.at(str).val.bits.size();
2515 if (!children.empty()) {
2516 if (children.size() != 1 || children.at(0)->type !=
AST_RANGE)
2517 log_error(
"Memory access in constant function is not supported in %s:%d (called from %s:%d).\n",
2519 children.at(0)->replace_variables(variables, fcall);
2520 while (simplify(
true,
false,
false, 1, -1,
false,
true)) { }
2521 if (!children.at(0)->range_valid)
2522 log_error(
"Non-constant range in %s:%d (called from %s:%d).\n",
2524 offset = std::min(children.at(0)->range_left, children.at(0)->range_right);
2525 width = std::min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);
2527 offset -= variables.at(str).offset;
2528 std::vector<RTLIL::State> &var_bits = variables.at(str).val.bits;
2529 std::vector<RTLIL::State> new_bits(var_bits.begin() + offset, var_bits.begin() + offset + width);
2530 AstNode *newNode = mkconst_bits(new_bits, variables.at(str).is_signed);
2536 for (
auto &child : children)
2537 child->replace_variables(variables, fcall);
2543 std::map<std::string, AstNode*> backup_scope;
2544 std::map<std::string, AstNode::varinfo_t>
variables;
2545 bool delete_temp_block =
false;
2549 for (
auto child : children)
2560 while (child->simplify(
true,
false,
false, 1, -1,
false,
true)) { }
2561 if (!child->range_valid)
2562 log_error(
"Can't determine size of variable %s in %s:%d (called from %s:%d).\n",
2563 child->str.c_str(), child->filename.c_str(), child->linenum, fcall->
filename.c_str(), fcall->
linenum);
2565 variables[child->str].offset = std::min(child->range_left, child->range_right);
2566 variables[child->str].is_signed = child->is_signed;
2567 if (child->is_input && argidx < fcall->children.size())
2568 variables[child->str].val = fcall->
children.at(argidx++)->bitsAsConst(variables[child->str].val.bits.size());
2575 delete_temp_block =
true;
2577 block->
children.push_back(child->clone());
2588 log(
"-----------------------------------\n");
2589 for (
auto &it : variables)
2590 log(
"%20s %40s\n", it.first.c_str(),
log_signal(it.second.val));
2596 stmt->
children.at(1)->replace_variables(variables, fcall);
2597 while (stmt->
simplify(
true,
false,
false, 1, -1,
false,
true)) { }
2603 log_error(
"Non-constant expression in constant function at %s:%d (called from %s:%d). X\n",
2607 log_error(
"Unsupported composite left hand side in constant function at %s:%d (called from %s:%d).\n",
2610 if (!variables.count(stmt->
children.at(0)->str))
2611 log_error(
"Assignment to non-local variable in constant function at %s:%d (called from %s:%d).\n",
2614 if (stmt->
children.at(0)->children.empty()) {
2615 variables[stmt->
children.at(0)->str].val = stmt->
children.at(1)->bitsAsConst(variables[stmt->
children.at(0)->str].val.bits.size());
2619 log_error(
"Non-constant range in %s:%d (called from %s:%d).\n",
2625 for (
int i = 0; i < width; i++)
2648 while (cond->
simplify(
true,
false,
false, 1, -1,
false,
true)) { }
2651 log_error(
"Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
2669 while (num->
simplify(
true,
false,
false, 1, -1,
false,
true)) { }
2672 log_error(
"Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
2688 while (expr->
simplify(
true,
false,
false, 1, -1,
false,
true)) { }
2691 for (
size_t i = 1; i < stmt->
children.size(); i++)
2693 bool found_match =
false;
2697 sel_case = stmt->
children.at(i)->children.back();
2701 for (
size_t j = 0; j+1 < stmt->
children.at(i)->children.size() && !found_match; j++)
2707 while (cond->
simplify(
true,
false,
false, 1, -1,
false,
true)) { }
2710 log_error(
"Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
2713 found_match = cond->
asBool();
2718 sel_case = stmt->
children.at(i)->children.back();
2740 log_error(
"Unsupported language construct in constant function at %s:%d (called from %s:%d).\n",
2745 if (delete_temp_block)
2748 for (
auto &it : backup_scope)
2749 if (it.second ==
NULL)
std::map< std::string, AstNode * > current_scope
static std::string next_token(bool pass_newline=false)
RTLIL::Const bitsAsConst(int width, bool is_signed)
RTLIL::Const const_logic_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_xor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
static AstNode * mkconst_int(uint32_t v, bool is_signed, int width=32)
std::string stringf(const char *fmt,...)
RTLIL::Const const_pow(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
AstNode * current_top_block
AstNode * dpi_call(const std::string &rtype, const std::string &fname, const std::vector< std::string > &argtypes, const std::vector< AstNode * > &args)
void log_warning(const char *format,...)
RTLIL::Const const_ne(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
static AstNode * mkconst_bits(const std::vector< RTLIL::State > &v, bool is_signed)
RTLIL::Const const_eq(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
#define YOSYS_NAMESPACE_END
void dumpAst(FILE *f, std::string indent)
RTLIL::Const as_const() const
static std::string unescape_id(std::string str)
void mem2reg_as_needed_pass1(std::map< AstNode *, std::set< std::string >> &mem2reg_places, std::map< AstNode *, uint32_t > &mem2reg_flags, std::map< AstNode *, uint32_t > &proc_flags, uint32_t &status_flags)
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
static std::string idx(std::string str)
RTLIL::Const const_sub(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_logic_not(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
void(* set_line_num)(int)
std::map< RTLIL::IdString, AstNode * > attributes
void log_error(const char *format,...)
void extend_u0(int width, bool is_signed=false)
bool mem2reg_check(std::set< AstNode * > &mem2reg_set)
RTLIL::Const const_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
bool get_bool_attribute(RTLIL::IdString id)
RTLIL::Const const_ge(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_mul(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
static void replace_result_wire_name_in_function(AstNode *node, std::string &from, std::string &to)
static std::string escape_id(std::string str)
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN bool did_something
RTLIL::Const const_reduce_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
void cloneInto(AstNode *other)
static void mark_memories_assign_lhs_complex(std::map< AstNode *, std::set< std::string >> &mem2reg_places, std::map< AstNode *, uint32_t > &mem2reg_candidates, AstNode *that)
RTLIL::Const const_reduce_xor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
double asReal(bool is_signed)
RTLIL::Const const_sshl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_reduce_xnor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_xnor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
int GetSize(RTLIL::Wire *wire)
std::string decode_string() const
#define log_assert(_assert_expr_)
RTLIL::Const const_shr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_mod(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_shl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real=NULL)
AstNode * current_block_child
RTLIL::Const const_le(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_eqx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
AstNode * eval_const_function(AstNode *fcall)
RTLIL::Const const_sshr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
int as_int(bool is_signed=false) const
void meminfo(int &mem_width, int &mem_size, int &addr_bits)
void expand_genblock(std::string index_var, std::string prefix, std::map< std::string, std::string > &name_map)
std::string current_filename
RTLIL::Const const_logic_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_reduce_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
#define YOSYS_NAMESPACE_BEGIN
bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
RTLIL::Const const_nex(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_div(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_lt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
AstNode * current_ast_mod
void log(const char *format,...)
AstNode * readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr)
std::vector< RTLIL::State > bits
RTLIL::Const const_neg(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_add(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
std::vector< AstNode * > children
void replace_ids(const std::string &prefix, const std::map< std::string, std::string > &rules)
AST::AstNode * const2ast(std::string code, char case_type=0, bool warn_z=false)
std::string id(RTLIL::IdString internal_id, bool may_rename=true)
uint64_t asInt(bool is_signed)
RTLIL::Const const_reduce_bool(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
void replace_variables(std::map< std::string, varinfo_t > &variables, AstNode *fcall)
RTLIL::Const const_pos(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
RTLIL::Const const_gt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
void mem2reg_as_needed_pass2(std::set< AstNode * > &mem2reg_set, AstNode *mod, AstNode *block)
const char * log_id(RTLIL::IdString str)
YOSYS_NAMESPACE_BEGIN int autoidx
RTLIL::Const const_not(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
bool has_const_only_constructs(bool &recommend_const_eval)