mirror of https://github.com/YosysHQ/yosys.git
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:
parent
c79fbfe0a1
commit
2e697f5655
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue