From 224109151da988618ede22c284a218e9bb3f3c06 Mon Sep 17 00:00:00 2001 From: Rahul Bhagwat Date: Sat, 8 Nov 2025 23:05:10 +0530 Subject: [PATCH 1/3] add specific package imports and tests --- frontends/ast/simplify.cc | 25 +++++++++++++- frontends/verilog/verilog_parser.y | 33 ++++++++++++++++++- tests/verilog/package_import_specific.sv | 14 ++++++++ tests/verilog/package_import_specific.ys | 5 +++ .../verilog/package_import_specific_module.sv | 16 +++++++++ 5 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 tests/verilog/package_import_specific.sv create mode 100644 tests/verilog/package_import_specific.ys create mode 100644 tests/verilog/package_import_specific_module.sv diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 97abf7452..010f4e14f 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1123,16 +1123,39 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } if (package_node) { - // Import all names from the package into current scope + bool is_wildcard = child->children.empty(); + std::set import_items; + + // For specific imports, collect the list of items to import + if (!is_wildcard) { + for (auto& import_item : child->children) { + import_items.insert(import_item->str); + } + } + + // Import names from the package into current scope for (auto& pkg_child : package_node->children) { + // Check if this is a specific import and if this item should be imported + if (!is_wildcard && import_items.count(pkg_child->str) == 0) + continue; + if (pkg_child->type == AST_PARAMETER || pkg_child->type == AST_LOCALPARAM || pkg_child->type == AST_TYPEDEF || pkg_child->type == AST_FUNCTION || pkg_child->type == AST_TASK || pkg_child->type == AST_ENUM) { + // For wildcard imports, check if item already exists (from specific import) + if (is_wildcard && current_scope.count(pkg_child->str) > 0) + continue; current_scope[pkg_child->str] = pkg_child.get(); } if (pkg_child->type == AST_ENUM) { for (auto& enode : pkg_child->children) { log_assert(enode->type==AST_ENUM_ITEM); + // Check if this enum item should be imported + if (!is_wildcard && import_items.count(enode->str) == 0) + continue; + // For wildcard imports, check if item already exists (from specific import) + if (is_wildcard && current_scope.count(enode->str) > 0) + continue; if (current_scope.count(enode->str) == 0) current_scope[enode->str] = enode.get(); else diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index ef8427679..e6c7f3672 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -428,6 +428,7 @@ #include #include #include + #include #include "frontends/verilog/verilog_frontend.h" struct specify_target { @@ -462,6 +463,7 @@ using string_t = std::unique_ptr; using ast_t = std::unique_ptr; + using ast_list_t = std::vector; using al_t = std::unique_ptr>>; using specify_target_ptr_t = std::unique_ptr; using specify_triple_ptr_t = std::unique_ptr; @@ -557,6 +559,8 @@ %type struct_union %type asgn_binop inc_or_dec_op %type genvar_identifier +%type import_item_list +%type import_item %type specify_target %type specify_triple specify_opt_triple @@ -830,10 +834,37 @@ package_body_stmt: import_stmt: TOK_IMPORT hierarchical_id TOK_PACKAGESEP TOK_ASTER TOK_SEMICOL { - // Create an import node to track package imports + // Create an import node to track specific and wildcard package imports auto import_node = std::make_unique(@$, AST_IMPORT); import_node->str = *$2; extra->ast_stack.back()->children.push_back(std::move(import_node)); + } | + TOK_IMPORT hierarchical_id TOK_PACKAGESEP import_item_list TOK_SEMICOL { + // Create an import node to track specific package imports + auto import_node = std::make_unique(@$, AST_IMPORT); + import_node->str = *$2; + // Move children from import_item_list to import_node + import_node->children = std::move($4); + extra->ast_stack.back()->children.push_back(std::move(import_node)); + }; + +import_item_list: + import_item { + ast_list_t list; + list.push_back(std::move($1)); + $$ = std::move(list); + } | + import_item_list TOK_COMMA import_item { + $1.push_back(std::move($3)); + $$ = std::move($1); + }; + +import_item: + TOK_ID { + // Create a simple node to store the imported item name + auto item_node = std::make_unique(@$, AST_NONE); + item_node->str = *$1; + $$ = std::move(item_node); }; interface: diff --git a/tests/verilog/package_import_specific.sv b/tests/verilog/package_import_specific.sv new file mode 100644 index 000000000..97004ed56 --- /dev/null +++ b/tests/verilog/package_import_specific.sv @@ -0,0 +1,14 @@ +package package_import_specific; + + localparam integer + DATA_WIDTH = 8, + ADDR_WIDTH = 4; + + localparam logic [2:0] + IDLE = 3'b000, + START = 3'b001, + DATA = 3'b010, + STOP = 3'b100, + DONE = 3'b101; + +endpackage diff --git a/tests/verilog/package_import_specific.ys b/tests/verilog/package_import_specific.ys new file mode 100644 index 000000000..8b183aac4 --- /dev/null +++ b/tests/verilog/package_import_specific.ys @@ -0,0 +1,5 @@ +read_verilog -sv package_import_specific.sv +read_verilog -sv package_import_specific_module.sv +hierarchy -check +proc +opt -full diff --git a/tests/verilog/package_import_specific_module.sv b/tests/verilog/package_import_specific_module.sv new file mode 100644 index 000000000..a568af4d2 --- /dev/null +++ b/tests/verilog/package_import_specific_module.sv @@ -0,0 +1,16 @@ +import package_import_specific::DATA_WIDTH; +import package_import_specific::IDLE; + +module package_import_specific_module; + logic [DATA_WIDTH-1:0] data; + logic [3:0] addr; + logic [2:0] state; + + always_comb begin + case (state) + IDLE: data = 8'h00; + default: data = 8'hFF; + endcase + end + +endmodule From 54e5eb1c3c7dea139401e811564bbf2e9ca91f60 Mon Sep 17 00:00:00 2001 From: Rahul Bhagwat Date: Sat, 8 Nov 2025 23:16:52 +0530 Subject: [PATCH 2/3] no use vector --- frontends/verilog/verilog_parser.y | 35 ++++++++++-------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index e6c7f3672..684727d5b 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -428,7 +428,6 @@ #include #include #include - #include #include "frontends/verilog/verilog_frontend.h" struct specify_target { @@ -463,7 +462,6 @@ using string_t = std::unique_ptr; using ast_t = std::unique_ptr; - using ast_list_t = std::vector; using al_t = std::unique_ptr>>; using specify_target_ptr_t = std::unique_ptr; using specify_triple_ptr_t = std::unique_ptr; @@ -559,8 +557,6 @@ %type struct_union %type asgn_binop inc_or_dec_op %type genvar_identifier -%type import_item_list -%type import_item %type specify_target %type specify_triple specify_opt_triple @@ -833,38 +829,31 @@ package_body_stmt: typedef_decl | localparam_decl | param_decl | task_func_decl; import_stmt: - TOK_IMPORT hierarchical_id TOK_PACKAGESEP TOK_ASTER TOK_SEMICOL { - // Create an import node to track specific and wildcard package imports + TOK_IMPORT TOK_ID TOK_PACKAGESEP TOK_ASTER TOK_SEMICOL { + // Create an import node to track wildcard package imports auto import_node = std::make_unique(@$, AST_IMPORT); import_node->str = *$2; extra->ast_stack.back()->children.push_back(std::move(import_node)); } | - TOK_IMPORT hierarchical_id TOK_PACKAGESEP import_item_list TOK_SEMICOL { - // Create an import node to track specific package imports - auto import_node = std::make_unique(@$, AST_IMPORT); + TOK_IMPORT TOK_ID TOK_PACKAGESEP { + // Start a specific import: create and push the AST_IMPORT node + AstNode* import_node = extra->pushChild(std::make_unique(@$, AST_IMPORT)); import_node->str = *$2; - // Move children from import_item_list to import_node - import_node->children = std::move($4); - extra->ast_stack.back()->children.push_back(std::move(import_node)); + } import_item_list TOK_SEMICOL { + // Done collecting specific items, pop the AST_IMPORT node + extra->ast_stack.pop_back(); }; import_item_list: - import_item { - ast_list_t list; - list.push_back(std::move($1)); - $$ = std::move(list); - } | - import_item_list TOK_COMMA import_item { - $1.push_back(std::move($3)); - $$ = std::move($1); - }; + import_item | + import_item_list TOK_COMMA import_item ; import_item: TOK_ID { - // Create a simple node to store the imported item name + // Append this specific import name under the current AST_IMPORT auto item_node = std::make_unique(@$, AST_NONE); item_node->str = *$1; - $$ = std::move(item_node); + extra->ast_stack.back()->children.push_back(std::move(item_node)); }; interface: From 8f53d21ea7eaec66ab93cb611f36fbf9e798935b Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 10 Nov 2025 14:26:10 +0100 Subject: [PATCH 3/3] simplify: refactor specific package import --- frontends/ast/simplify.cc | 85 ++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 010f4e14f..308406591 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -889,6 +889,52 @@ static void check_auto_nosync(AstNode *node) check_auto_nosync(child.get()); } +class PackageImporter { + std::set import_items; + bool is_wildcard; + const AstNode* node; +public: + PackageImporter(const AstNode* n, const AstNode* child) : node(n) { + is_wildcard = child->children.empty(); + // For specific imports, collect the list of items to import + if (!is_wildcard) { + for (auto& item : child->children) { + import_items.insert(item->str); + } + } + } + + void import(std::map& scope, AstNode* to_import) const { + // Check if this is a specific import and if this item should be imported + if (!is_wildcard && import_items.count(to_import->str) == 0) + return; + + if (to_import->type == AST_PARAMETER || to_import->type == AST_LOCALPARAM || + to_import->type == AST_TYPEDEF || to_import->type == AST_FUNCTION || + to_import->type == AST_TASK || to_import->type == AST_ENUM) { + // For wildcard imports, check if item already exists (from specific import) + if (is_wildcard && scope.count(to_import->str) > 0) + return; + scope[to_import->str] = to_import; + } + if (to_import->type == AST_ENUM) { + for (auto& enode : to_import->children) { + log_assert(enode->type==AST_ENUM_ITEM); + // Check if this enum item should be imported + if (!is_wildcard && import_items.count(enode->str) == 0) + continue; + // For wildcard imports, check if item already exists (from specific import) + if (is_wildcard && scope.count(enode->str) > 0) + continue; + if (scope.count(enode->str) == 0) + scope[enode->str] = enode.get(); + else + node->input_error("enum item %s already exists in current scope\n", enode->str); + } + } + } +}; + // convert the AST into a simpler AST that has all parameters substituted by their // values, unrolled for-loops, expanded generate blocks, etc. when this function // is done with an AST it can be converted into RTLIL using genRTLIL(). @@ -1123,45 +1169,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } if (package_node) { - bool is_wildcard = child->children.empty(); - std::set import_items; - - // For specific imports, collect the list of items to import - if (!is_wildcard) { - for (auto& import_item : child->children) { - import_items.insert(import_item->str); - } - } - + PackageImporter importer(this, child); // Import names from the package into current scope for (auto& pkg_child : package_node->children) { - // Check if this is a specific import and if this item should be imported - if (!is_wildcard && import_items.count(pkg_child->str) == 0) - continue; - - if (pkg_child->type == AST_PARAMETER || pkg_child->type == AST_LOCALPARAM || - pkg_child->type == AST_TYPEDEF || pkg_child->type == AST_FUNCTION || - pkg_child->type == AST_TASK || pkg_child->type == AST_ENUM) { - // For wildcard imports, check if item already exists (from specific import) - if (is_wildcard && current_scope.count(pkg_child->str) > 0) - continue; - current_scope[pkg_child->str] = pkg_child.get(); - } - if (pkg_child->type == AST_ENUM) { - for (auto& enode : pkg_child->children) { - log_assert(enode->type==AST_ENUM_ITEM); - // Check if this enum item should be imported - if (!is_wildcard && import_items.count(enode->str) == 0) - continue; - // For wildcard imports, check if item already exists (from specific import) - if (is_wildcard && current_scope.count(enode->str) > 0) - continue; - if (current_scope.count(enode->str) == 0) - current_scope[enode->str] = enode.get(); - else - input_error("enum item %s already exists in current scope\n", enode->str); - } - } + importer.import(current_scope, pkg_child.get()); } // Remove the import node since it's been processed children.erase(children.begin() + i);