void expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map);
void replace_ids(std::map<std::string, std::string> &rules);
void mem2reg_as_needed_pass1(std::set<AstNode*> &mem2reg_set, std::set<AstNode*> &mem2reg_candidates, bool sync_proc, bool async_proc);
- void mem2reg_as_needed_pass2(std::set<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block);
+ void mem2reg_as_needed_pass2(std::set<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block, AstNode *top_block);
void meminfo(int &mem_width, int &mem_size, int &addr_bits);
// create a human-readable text representation of the AST (for debugging)
}
}
- mem2reg_as_needed_pass2(mem2reg_set, this, NULL);
+ mem2reg_as_needed_pass2(mem2reg_set, this, NULL, NULL);
for (size_t i = 0; i < children.size(); i++) {
if (mem2reg_set.count(children[i]) > 0) {
}
mem2reg_candidates.insert(children[0]->id2ast);
}
+
+ if (type == AST_MEMORY && attributes.count("\\mem2reg") > 0)
+ mem2reg_set.insert(this);
if (type == AST_ALWAYS) {
for (auto child : children) {
}
// actually replace memories with registers
-void AstNode::mem2reg_as_needed_pass2(std::set<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block)
+void AstNode::mem2reg_as_needed_pass2(std::set<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block, AstNode *top_block)
{
if (type == AST_BLOCK)
block = this;
wire_data->is_reg = true;
mod->children.push_back(wire_data);
+ assert(top_block != NULL);
+ std::vector<RTLIL::State> x_bits;
+ x_bits.push_back(RTLIL::State::Sx);
+
+ AstNode *assign_addr_x = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), AstNode::mkconst_bits(x_bits, false));
+ assign_addr_x->children[0]->str = id_addr;
+ top_block->children.insert(top_block->children.begin(), assign_addr_x);
+
+ AstNode *assign_data_x = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), AstNode::mkconst_bits(x_bits, false));
+ assign_data_x->children[0]->str = id_data;
+ top_block->children.insert(top_block->children.begin(), assign_data_x);
+
assert(block != NULL);
size_t assign_idx = 0;
while (assign_idx < block->children.size() && block->children[assign_idx] != this)
cond_node->children[1]->children.push_back(assign_reg);
case_node->children.push_back(cond_node);
+ if (top_block)
+ {
+ AstNode *assign_addr_x = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), AstNode::mkconst_bits(x_bits, false));
+ assign_addr_x->children[0]->str = id_addr;
+ top_block->children.insert(top_block->children.begin(), assign_addr_x);
+
+ AstNode *assign_data_x = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), AstNode::mkconst_bits(x_bits, false));
+ assign_data_x->children[0]->str = id_data;
+ top_block->children.insert(top_block->children.begin(), assign_data_x);
+ }
+
if (block)
{
size_t assign_idx = 0;
assert(id2ast == NULL || mem2reg_set.count(id2ast) == 0);
- for (size_t i = 0; i < children.size(); i++)
- children[i]->mem2reg_as_needed_pass2(mem2reg_set, mod, block);
+ auto children_list = children;
+ for (size_t i = 0; i < children_list.size(); i++) {
+ if (type == AST_ALWAYS && children_list[i]->type == AST_BLOCK)
+ top_block = children_list[i];
+ children_list[i]->mem2reg_as_needed_pass2(mem2reg_set, mod, block, top_block);
+ }
}
// calulate memory dimensions