diff options
author | Clifford Wolf <clifford@clifford.at> | 2016-08-21 13:23:58 +0200 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2016-08-21 13:23:58 +0200 |
commit | 82a4a0230feedd994546ad57a1f4ae79b8f80136 (patch) | |
tree | 070e0753a17f8e146c6a6c40ad2bb9a4e556ad5e | |
parent | dbdd8927e78622885bc85c429e783b89b2d3022d (diff) | |
download | yosys-82a4a0230feedd994546ad57a1f4ae79b8f80136.tar.gz yosys-82a4a0230feedd994546ad57a1f4ae79b8f80136.tar.bz2 yosys-82a4a0230feedd994546ad57a1f4ae79b8f80136.zip |
Another bugfix in mem2reg code
-rw-r--r-- | frontends/ast/ast.h | 2 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 2 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 34 | ||||
-rw-r--r-- | tests/simple/mem2reg.v | 22 |
4 files changed, 53 insertions, 7 deletions
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 530c11ba5..fed5ad067 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -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); diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 115f8d122..218ce1d7d 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -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: diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index d071a54fa..c957389c3 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -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; diff --git a/tests/simple/mem2reg.v b/tests/simple/mem2reg.v index b1ab04d62..23094c10a 100644 --- a/tests/simple/mem2reg.v +++ b/tests/simple/mem2reg.v @@ -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 + |