verilog: check entire user type stack for type definition
authorXiretza <xiretza@xiretza.xyz>
Thu, 18 Mar 2021 20:53:02 +0000 (21:53 +0100)
committerZachary Snow <zachary.j.snow@gmail.com>
Sun, 21 Mar 2021 23:35:13 +0000 (19:35 -0400)
frontends/verilog/verilog_parser.y
tests/svtypes/typedef_scopes.sv

index 91b7afddfaa2c7ffe78b2740cc86e2ca469eefb5..e4b3258c23f39ed85d198847e92d2bad319ae015 100644 (file)
@@ -163,12 +163,18 @@ static bool isInLocalScope(const std::string *name)
 
 static AstNode *getTypeDefinitionNode(std::string type_name)
 {
-       // return the definition nodes from the typedef statement
-       auto user_types = user_type_stack.back();
-       log_assert(user_types->count(type_name) > 0);
-       auto typedef_node = (*user_types)[type_name];
-       log_assert(typedef_node->type == AST_TYPEDEF);
-       return typedef_node->children[0];
+       // check current scope then outer scopes for a name
+       for (auto it = user_type_stack.rbegin(); it != user_type_stack.rend(); ++it) {
+               if ((*it)->count(type_name) > 0) {
+                       // return the definition nodes from the typedef statement
+                       auto typedef_node = (**it)[type_name];
+                       log_assert(typedef_node->type == AST_TYPEDEF);
+                       return typedef_node->children[0];
+               }
+       }
+
+       // The lexer recognized the name as a TOK_USER_TYPE, but now we can't find it anymore?
+       log_error("typedef for user type `%s' not found", type_name.c_str());
 }
 
 static AstNode *copyTypeDefinition(std::string type_name)
index 5507d84f28e3c540f1fa7fd4cca1c20f6562fc2b..9a898fac8a4e4dd2931f67d466767a86bcc1b85a 100644 (file)
@@ -4,6 +4,7 @@ typedef enum logic {s0, s1} outer_enum_t;
 
 module top;
 
+       // globals are inherited
        outer_uint4_t u4_i = 8'hA5;
        outer_enum_t enum4_i = s0;
        always @(*) assert(u4_i == 4'h5);
@@ -17,13 +18,22 @@ module top;
        always @(*) assert(inner_enum1 == 3'h3);
 
        if (1) begin: genblock
+               // type declarations in child scopes shadow their parents
                typedef logic [7:0] inner_type;
                parameter inner_type inner_const = 8'hA5;
                typedef enum logic [2:0] {s5=5, s6, s7} inner_enum_t;
+
                inner_type inner_gb_i = inner_const; //8'hA5;
                inner_enum_t inner_gb_enum1 = s7;
                always @(*) assert(inner_gb_i == 8'hA5);
                always @(*) assert(inner_gb_enum1 == 3'h7);
+
+               // check that copying of struct member types works over multiple type scopes
+               typedef struct packed {
+                       outer_uint4_t x;
+               } mystruct_t;
+               mystruct_t mystruct;
+               always @(*) assert($bits(mystruct) == 4);
        end
 
        inner_type inner_i2 = 8'h42;