further improved const function support
authorClifford Wolf <clifford@clifford.at>
Fri, 6 Jun 2014 22:02:05 +0000 (00:02 +0200)
committerClifford Wolf <clifford@clifford.at>
Fri, 6 Jun 2014 22:02:05 +0000 (00:02 +0200)
frontends/ast/ast.h
frontends/ast/genrtlil.cc
frontends/ast/simplify.cc

index 6c5a0eae4c59b836fde176ec2bbc7f42487f486c..3e69e3bc06401826fa83a6ecd4ea0b0d430b6cc5 100644 (file)
@@ -202,7 +202,7 @@ namespace AST
 
                // additional functionality for evaluating constant functions
                struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; };
-               bool has_const_only_constructs();
+               bool has_const_only_constructs(bool &recommend_const_eval);
                void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall);
                AstNode *eval_const_function(AstNode *fcall);
 
index 2efdee10ace843165a7dcd5df39e230a39cb0c79..9273636f454774c989a3f71f4d50fbc0dc4b4000 100644 (file)
@@ -623,10 +623,10 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint)
                                if (id_ast->type == AST_AUTOWIRE)
                                        this_width = 1;
                                else {
-                                       // current_ast_mod->dumpAst(stdout, "");
-                                       // printf("---\n");
-                                       // dumpAst(stdout, "");
-                                       // fflush(stdout);
+                                       // current_ast_mod->dumpAst(NULL, "mod> ");
+                                       // log("---\n");
+                                       // id_ast->dumpAst(NULL, "decl> ");
+                                       // dumpAst(NULL, "ref> ");
                                        log_error("Failed to detect with of signal access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
                                }
                        } else {
@@ -693,7 +693,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint)
                break;
 
        case AST_REPLICATE:
-               while (children[0]->simplify(true, false, false, 1, -1, false, false) == true) { }
+               while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }
                if (children[0]->type != AST_CONSTANT)
                        log_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum);
                children[1]->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
index 71e7cbc6d606c1377cb0347d130e2364f58c6626..8a4d42e1bcea893b1b6fcbc1432c693a637ee98f 100644 (file)
@@ -349,12 +349,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
        }
 
        if (detect_width_simple && width_hint < 0) {
+               if (type == AST_REPLICATE)
+                       while (children[0]->simplify(true, false, in_lvalue, stage, -1, false, true) == true)
+                               did_something = true;
                for (auto child : children)
                        while (!child->basic_prep && child->simplify(false, false, in_lvalue, stage, -1, false, in_param) == true)
                                did_something = true;
-               if (type == AST_REPLICATE)
-                       while (children[0]->simplify(true, false, in_lvalue, stage, -1, false, in_param) == true)
-                               did_something = true;
                detectSignWidth(width_hint, sign_hint);
        }
 
@@ -376,8 +376,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                        bool const_fold_here = const_fold, in_lvalue_here = in_lvalue;
                        int width_hint_here = width_hint;
                        bool sign_hint_here = sign_hint;
-                       if (i == 0 && type == AST_REPLICATE)
-                               const_fold_here = true;
+                       bool in_param_here = in_param;
+                       if (i == 0 && (type == AST_REPLICATE || type == AST_WIRE))
+                               const_fold_here = true, in_param_here = true;
                        if (type == AST_PARAMETER || type == AST_LOCALPARAM)
                                const_fold_here = true;
                        if (i == 0 && (type == AST_ASSIGN || type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE))
@@ -394,7 +395,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                                width_hint_here = -1, sign_hint_here = false;
                        if (children_are_self_determined)
                                width_hint_here = -1, sign_hint_here = false;
-                       did_something_here = children[i]->simplify(const_fold_here, at_zero, in_lvalue_here, stage, width_hint_here, sign_hint_here, in_param);
+                       did_something_here = children[i]->simplify(const_fold_here, at_zero, in_lvalue_here, stage, width_hint_here, sign_hint_here, in_param_here);
                        if (did_something_here)
                                did_something = true;
                }
@@ -1187,7 +1188,9 @@ skip_dynamic_range_lvalue_expansion:;
                                log_error("Can't resolve task name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
                }
 
-               if (in_param || current_scope[str]->has_const_only_constructs())
+               bool recommend_const_eval = false;
+               bool require_const_eval = in_param ? false : has_const_only_constructs(recommend_const_eval);
+               if (in_param || recommend_const_eval || require_const_eval)
                {
                        bool all_args_const = true;
                        for (auto child : children) {
@@ -1205,7 +1208,7 @@ skip_dynamic_range_lvalue_expansion:;
 
                        if (in_param)
                                log_error("Non-constant function call in constant expression at %s:%d.\n", filename.c_str(), linenum);
-                       else
+                       if (require_const_eval)
                                log_error("Function %s can only be called with constant arguments at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
                }
 
@@ -1828,15 +1831,17 @@ void AstNode::meminfo(int &mem_width, int &mem_size, int &addr_bits)
                addr_bits++;
 }
 
-bool AstNode::has_const_only_constructs()
+bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
 {
+       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())
+               if (current_scope[str]->has_const_only_constructs(recommend_const_eval))
                        return true;
        for (auto child : children)
-               if (child->AstNode::has_const_only_constructs())
+               if (child->AstNode::has_const_only_constructs(recommend_const_eval))
                        return true;
        return false;
 }