aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--frontends/ast/ast.h2
-rw-r--r--frontends/ast/genrtlil.cc2
-rw-r--r--frontends/ast/simplify.cc34
-rw-r--r--tests/simple/mem2reg.v22
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
+