From 1bbea13f80fa7e5d337dcf3affd28d1ab8664cae Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Thu, 4 Jan 2024 17:22:07 +0100 Subject: [PATCH] Correct hierarchical path names for structs and unions --- frontends/ast/simplify.cc | 36 ++++++++++++++++++--------------- tests/svtypes/typedef_scopes.sv | 6 +++--- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 2a500b56b..dfa1ed6af 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -226,17 +226,6 @@ void AstNode::annotateTypedEnums(AstNode *template_node) } } -static bool name_has_dot(const std::string &name, std::string &struct_name) -{ - // check if plausible struct member name \sss.mmm - std::string::size_type pos; - if (name.substr(0, 1) == "\\" && (pos = name.find('.', 0)) != std::string::npos) { - struct_name = name.substr(0, pos); - return true; - } - return false; -} - static AstNode *make_range(int left, int right, bool is_signed = false) { // generate a pre-validated range node for a fixed signal range. @@ -2185,11 +2174,24 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (type == AST_IDENTIFIER && !basic_prep) { // check if a plausible struct member sss.mmmm - std::string sname; - if (name_has_dot(str, sname)) { - if (current_scope.count(str) > 0) { - auto item_node = current_scope[str]; - if (item_node->type == AST_STRUCT_ITEM || item_node->type == AST_STRUCT || item_node->type == AST_UNION) { + if (!str.empty() && str[0] == '\\' && current_scope.count(str)) { + auto item_node = current_scope[str]; + if (item_node->type == AST_STRUCT_ITEM || item_node->type == AST_STRUCT || item_node->type == AST_UNION) { + // Traverse any hierarchical path until the full name for the referenced struct/union is found. + std::string sname; + bool found_sname = false; + for (std::string::size_type pos = 0; (pos = str.find('.', pos)) != std::string::npos; pos++) { + sname = str.substr(0, pos); + if (current_scope.count(sname)) { + auto stype = current_scope[sname]->type; + if (stype == AST_WIRE || stype == AST_PARAMETER || stype == AST_LOCALPARAM) { + found_sname = true; + break; + } + } + } + + if (found_sname) { // structure member, rewrite this node to reference the packed struct wire auto range = make_struct_member_range(this, item_node); newNode = new AstNode(AST_IDENTIFIER, range); @@ -4681,6 +4683,8 @@ void AstNode::expand_genblock(const std::string &prefix) switch (child->type) { case AST_WIRE: case AST_MEMORY: + case AST_STRUCT: + case AST_UNION: case AST_PARAMETER: case AST_LOCALPARAM: case AST_FUNCTION: diff --git a/tests/svtypes/typedef_scopes.sv b/tests/svtypes/typedef_scopes.sv index 5ac9a4664..cd7b7953e 100644 --- a/tests/svtypes/typedef_scopes.sv +++ b/tests/svtypes/typedef_scopes.sv @@ -45,12 +45,12 @@ module top; localparam W = 10; typedef T U; typedef logic [W-1:0] V; - struct packed { + typedef struct packed { logic [W-1:0] x; // width 10 U y; // width 5 V z; // width 10 - } shadow; - // This currently only works as long as long as shadow is not typedef'ed + } shadow_t; + shadow_t shadow; always @(*) assert($bits(shadow.x) == 10); always @(*) assert($bits(shadow.y) == 5); always @(*) assert($bits(shadow.z) == 10);