diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 9887d24ea..b6b15b738 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -326,6 +326,9 @@ namespace AST // helpers for locations std::string loc_string() const; + + // Helper for looking up identifiers which are prefixed with the current module name + std::string try_pop_module_prefix() const; }; // process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index b8b9f715e..e886844be 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -767,8 +767,15 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun case AST_IDENTIFIER: id_ast = id2ast; - if (id_ast == NULL && current_scope.count(str)) - id_ast = current_scope.at(str); + if (!id_ast) { + if (current_scope.count(str)) + id_ast = current_scope[str]; + else { + std::string alt = try_pop_module_prefix(); + if (current_scope.count(alt)) + id_ast = current_scope[alt]; + } + } if (!id_ast) log_file_error(filename, location.first_line, "Failed to resolve identifier %s for width detection!\n", str.c_str()); if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM || id_ast->type == AST_ENUM_ITEM) { diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 44b11da74..cd27a720a 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1698,17 +1698,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_IDENTIFIER) { if (current_scope.count(str) == 0) { AstNode *current_scope_ast = (current_ast_mod == nullptr) ? current_ast : current_ast_mod; - size_t pos = str.find('.', 1); - if (str[0] == '\\' && pos != std::string::npos) { - std::string new_str = "\\" + str.substr(pos + 1); - if (current_scope.count(new_str)) { - std::string prefix = str.substr(0, pos); - auto it = current_scope_ast->attributes.find(ID::hdlname); - if ((it != current_scope_ast->attributes.end() && it->second->str == prefix) - || prefix == current_scope_ast->str) - str = new_str; - } - } + str = try_pop_module_prefix(); for (auto node : current_scope_ast->children) { //log("looking at mod scope child %s\n", type2str(node->type).c_str()); switch (node->type) { @@ -5124,4 +5114,21 @@ std::pair AstNode::get_tern_choice() return {choice, not_choice}; } +std::string AstNode::try_pop_module_prefix() const +{ + AstNode *current_scope_ast = (current_ast_mod == nullptr) ? current_ast : current_ast_mod; + size_t pos = str.find('.', 1); + if (str[0] == '\\' && pos != std::string::npos) { + std::string new_str = "\\" + str.substr(pos + 1); + if (current_scope.count(new_str)) { + std::string prefix = str.substr(0, pos); + auto it = current_scope_ast->attributes.find(ID::hdlname); + if ((it != current_scope_ast->attributes.end() && it->second->str == prefix) + || prefix == current_scope_ast->str) + return new_str; + } + } + return str; +} + YOSYS_NAMESPACE_END diff --git a/tests/simple/module_scope_case.v b/tests/simple/module_scope_case.v new file mode 100644 index 000000000..1472b6912 --- /dev/null +++ b/tests/simple/module_scope_case.v @@ -0,0 +1,11 @@ +module top( + input wire x, + output reg y +); + always @* begin + case (top.x) + 1: top.y = 0; + 0: top.y = 1; + endcase + end +endmodule