verilog: check for module scope identifiers during width detection

The recent fix for case expression width detection causes the width of
the expressions to be queried before they are simplified. Because the
logic supporting module scope identifiers only existed in simplify,
looking them up would fail during width detection. This moves the logic
to a common helper used in both simplify() and detectSignWidthWorker().
This commit is contained in:
Zachary Snow 2021-06-05 16:21:09 -04:00 committed by Zachary Snow
parent c79fbfe0a1
commit 2e697f5655
4 changed files with 41 additions and 13 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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*, AstNode*> 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

View File

@ -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