aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/ast/simplify.cc
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/ast/simplify.cc')
-rw-r--r--frontends/ast/simplify.cc70
1 files changed, 61 insertions, 9 deletions
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index fb6623f02..fc2976c83 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -1205,6 +1205,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
current_block = this;
current_block_child = children[i];
}
+ if (!in_param_here && type == AST_FCALL) {
+ bool recommend_const_eval = false;
+ bool require_const_eval = has_const_only_constructs(recommend_const_eval);
+ in_param_here = recommend_const_eval || require_const_eval;
+ }
if ((type == AST_ALWAYS || type == AST_INITIAL) && children[i]->type == AST_BLOCK)
current_top_block = children[i];
if (i == 0 && child_0_is_self_determined)
@@ -1325,6 +1330,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (template_node->type == AST_STRUCT || template_node->type == AST_UNION) {
// replace with wire representing the packed structure
newNode = make_packed_struct(template_node, str);
+ // add original input/output attribute to resolved wire
+ newNode->is_input = this->is_input;
+ newNode->is_output = this->is_output;
current_scope[str] = this;
goto apply_newNode;
}
@@ -3170,6 +3178,8 @@ skip_dynamic_range_lvalue_expansion:;
if (all_args_const) {
AstNode *func_workspace = current_scope[str]->clone();
+ func_workspace->str = NEW_ID.str();
+ func_workspace->replace_result_wire_name_in_function(str, func_workspace->str);
newNode = func_workspace->eval_const_function(this);
delete func_workspace;
goto apply_newNode;
@@ -3337,6 +3347,25 @@ skip_dynamic_range_lvalue_expansion:;
wire->type = AST_LOCALPARAM;
wire->attributes.erase(ID::nosync);
wire->children.insert(wire->children.begin(), arg->clone());
+ // args without a range implicitly have width 1
+ if (wire->children.back()->type != AST_RANGE) {
+ // check if this wire is redeclared with an explicit size
+ bool uses_explicit_size = false;
+ for (const AstNode *other_child : decl->children)
+ if (other_child->type == AST_WIRE && child->str == other_child->str
+ && !other_child->children.empty()
+ && other_child->children.back()->type == AST_RANGE) {
+ uses_explicit_size = true;
+ break;
+ }
+ if (!uses_explicit_size) {
+ AstNode* range = new AstNode();
+ range->type = AST_RANGE;
+ wire->children.push_back(range);
+ range->children.push_back(mkconst_int(0, true));
+ range->children.push_back(mkconst_int(0, true));
+ }
+ }
continue;
}
AstNode *wire_id = new AstNode(AST_IDENTIFIER);
@@ -3427,7 +3456,14 @@ replace_fcall_later:;
if (current_scope[str]->children[0]->isConst())
newNode = current_scope[str]->children[0]->clone();
}
- else if (at_zero && current_scope.count(str) > 0 && (current_scope[str]->type == AST_WIRE || current_scope[str]->type == AST_AUTOWIRE)) {
+ else if (at_zero && current_scope.count(str) > 0) {
+ AstNode *node = current_scope[str];
+ if (node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY)
+ newNode = mkconst_int(0, sign_hint, width_hint);
+ }
+ break;
+ case AST_MEMRD:
+ if (at_zero) {
newNode = mkconst_int(0, sign_hint, width_hint);
}
break;
@@ -3683,12 +3719,12 @@ apply_newNode:
return did_something;
}
-static void replace_result_wire_name_in_function(AstNode *node, std::string &from, std::string &to)
+void AstNode::replace_result_wire_name_in_function(const std::string &from, const std::string &to)
{
- for (auto &it : node->children)
- replace_result_wire_name_in_function(it, from, to);
- if (node->str == from)
- node->str = to;
+ for (AstNode *child : children)
+ child->replace_result_wire_name_in_function(from, to);
+ if (str == from && type != AST_FCALL && type != AST_TCALL)
+ str = to;
}
// replace a readmem[bh] TCALL ast node with a block of memory assignments
@@ -3881,7 +3917,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
name_map[child->str] = new_name;
if (child->type == AST_FUNCTION)
- replace_result_wire_name_in_function(child, child->str, new_name);
+ child->replace_result_wire_name_in_function(child->str, new_name);
else
child->str = new_name;
current_scope[new_name] = child;
@@ -4461,15 +4497,31 @@ bool AstNode::detect_latch(const std::string &var)
bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
{
+ std::set<std::string> visited;
+ return has_const_only_constructs(visited, recommend_const_eval);
+}
+
+bool AstNode::has_const_only_constructs(std::set<std::string>& visited, bool &recommend_const_eval)
+{
+ if (type == AST_FUNCTION || type == AST_TASK)
+ {
+ if (visited.count(str))
+ {
+ recommend_const_eval = true;
+ return false;
+ }
+ visited.insert(str);
+ }
+
if (type == AST_FOR)
recommend_const_eval = true;
if (type == AST_WHILE || type == AST_REPEAT)
return true;
if (type == AST_FCALL && current_scope.count(str))
- if (current_scope[str]->has_const_only_constructs(recommend_const_eval))
+ if (current_scope[str]->has_const_only_constructs(visited, recommend_const_eval))
return true;
for (auto child : children)
- if (child->AstNode::has_const_only_constructs(recommend_const_eval))
+ if (child->AstNode::has_const_only_constructs(visited, recommend_const_eval))
return true;
return false;
}