Another bugfix in mem2reg code
authorClifford Wolf <clifford@clifford.at>
Sun, 21 Aug 2016 11:23:58 +0000 (13:23 +0200)
committerClifford Wolf <clifford@clifford.at>
Sun, 21 Aug 2016 11:23:58 +0000 (13:23 +0200)
frontends/ast/ast.h
frontends/ast/genrtlil.cc
frontends/ast/simplify.cc
tests/simple/mem2reg.v

index 530c11ba59d76484a085c53c2eeed5232e6b355f..fed5ad06752bcaf27efd953f1690e6671f003e80 100644 (file)
@@ -220,7 +220,7 @@ namespace AST
                void replace_ids(const std::string &prefix, const std::map<std::string, std::string> &rules);
                void mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg_places,
                                dict<AstNode*, uint32_t> &mem2reg_flags, dict<AstNode*, uint32_t> &proc_flags, uint32_t &status_flags);
-               bool mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block);
+               bool mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block, AstNode *&async_block);
                bool mem2reg_check(pool<AstNode*> &mem2reg_set);
                void mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes);
                void meminfo(int &mem_width, int &mem_size, int &addr_bits);
index 115f8d1220f3be4a4e0e695a4b85e8f542a10563..218ce1d7d2494aa8e79acdae7caded0eee1761a5 100644 (file)
@@ -540,6 +540,7 @@ struct AST_INTERNAL::ProcessGenerator
                        log_error("Found parameter declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum);
                        break;
 
+               case AST_NONE:
                case AST_TCALL:
                case AST_FOR:
                        break;
@@ -810,6 +811,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
        // simply ignore this nodes.
        // they are either leftovers from simplify() or are referenced by other nodes
        // and are only accessed here thru this references
+       case AST_NONE:
        case AST_TASK:
        case AST_FUNCTION:
        case AST_DPI_FUNCTION:
index d071a54fa09ce16bf5d61817e4224b06eb3be0e4..c957389c342a5f1e17c0f8ffeeb020753cb0e155 100644 (file)
@@ -148,7 +148,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                                }
                        }
 
-                       while (mem2reg_as_needed_pass2(mem2reg_set, this, NULL)) { }
+                       AstNode *async_block = NULL;
+                       while (mem2reg_as_needed_pass2(mem2reg_set, this, NULL, async_block)) { }
 
                        vector<AstNode*> delnodes;
                        mem2reg_remove(mem2reg_set, delnodes);
@@ -2707,15 +2708,36 @@ void AstNode::mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &deln
 }
 
 // actually replace memories with registers
-bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block)
+bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block, AstNode *&async_block)
 {
        bool did_something = false;
 
        if (type == AST_BLOCK)
                block = this;
 
-       if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && block != NULL &&
-                       children[0]->mem2reg_check(mem2reg_set) && children[0]->children[0]->children[0]->type != AST_CONSTANT)
+       if (type == AST_FUNCTION || type == AST_TASK)
+               return false;
+
+       if (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set))
+       {
+               if (async_block == NULL) {
+                       async_block = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK));
+                       mod->children.push_back(async_block);
+               }
+
+               AstNode *newNode = clone();
+               newNode->type = AST_ASSIGN_EQ;
+               async_block->children[0]->children.push_back(newNode);
+
+               newNode = new AstNode(AST_NONE);
+               newNode->cloneInto(this);
+               delete newNode;
+
+               did_something = true;
+       }
+
+       if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->mem2reg_check(mem2reg_set) &&
+                       children[0]->children[0]->children[0]->type != AST_CONSTANT)
        {
                std::stringstream sstr;
                sstr << "$mem2reg_wr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
@@ -2791,7 +2813,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
                else
                {
                        std::stringstream sstr;
-                       sstr << "$mem2reg_rd$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
+                       sstr << "$mem2reg_rd$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++);
                        std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
 
                        int mem_width, mem_size, addr_bits;
@@ -2871,7 +2893,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
 
        auto children_list = children;
        for (size_t i = 0; i < children_list.size(); i++)
-               if (children_list[i]->mem2reg_as_needed_pass2(mem2reg_set, mod, block))
+               if (children_list[i]->mem2reg_as_needed_pass2(mem2reg_set, mod, block, async_block))
                        did_something = true;
 
        return did_something;
index b1ab04d62149075068b39a470f4cc2aed8a46ba7..23094c10a7f94583398f6bd06cd2738f2b475572 100644 (file)
@@ -59,3 +59,25 @@ always @(posedge clk)
 assign dout_b = dint_c[3];
 endmodule
 
+// ------------------------------------------------------
+
+module mem2reg_test4(result1, result2, result3);
+       output signed [9:0] result1;
+       output signed [9:0] result2;
+       output signed [9:0] result3;
+
+       wire signed [9:0] intermediate [0:3];
+
+       function integer depth2Index;
+               input integer depth;
+               depth2Index = depth;
+       endfunction
+
+       assign intermediate[depth2Index(1)] = 1;
+       assign intermediate[depth2Index(2)] = 2;
+       assign intermediate[3] = 3;
+       assign result1 = intermediate[1];
+       assign result2 = intermediate[depth2Index(2)];
+       assign result3 = intermediate[depth2Index(3)];
+endmodule
+