mirror of
https://github.com/YosysHQ/yosys
synced 2025-12-04 02:56:45 +00:00
Merge pull request #5477 from bhagwat-rahul/fix-non-wildcard-package-imports
Add support for specific package imports
This commit is contained in:
commit
6a22397c02
5 changed files with 106 additions and 17 deletions
|
|
@ -889,6 +889,52 @@ static void check_auto_nosync(AstNode *node)
|
|||
check_auto_nosync(child.get());
|
||||
}
|
||||
|
||||
class PackageImporter {
|
||||
std::set<std::string> 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<std::string, AstNode*>& 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,22 +1169,10 @@ 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
|
||||
PackageImporter importer(this, child);
|
||||
// Import names from the package into current scope
|
||||
for (auto& pkg_child : package_node->children) {
|
||||
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) {
|
||||
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);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -829,11 +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 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<AstNode>(@$, AST_IMPORT);
|
||||
import_node->str = *$2;
|
||||
extra->ast_stack.back()->children.push_back(std::move(import_node));
|
||||
} |
|
||||
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<AstNode>(@$, AST_IMPORT));
|
||||
import_node->str = *$2;
|
||||
} import_item_list TOK_SEMICOL {
|
||||
// Done collecting specific items, pop the AST_IMPORT node
|
||||
extra->ast_stack.pop_back();
|
||||
};
|
||||
|
||||
import_item_list:
|
||||
import_item |
|
||||
import_item_list TOK_COMMA import_item ;
|
||||
|
||||
import_item:
|
||||
TOK_ID {
|
||||
// Append this specific import name under the current AST_IMPORT
|
||||
auto item_node = std::make_unique<AstNode>(@$, AST_NONE);
|
||||
item_node->str = *$1;
|
||||
extra->ast_stack.back()->children.push_back(std::move(item_node));
|
||||
};
|
||||
|
||||
interface:
|
||||
|
|
|
|||
14
tests/verilog/package_import_specific.sv
Normal file
14
tests/verilog/package_import_specific.sv
Normal file
|
|
@ -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
|
||||
5
tests/verilog/package_import_specific.ys
Normal file
5
tests/verilog/package_import_specific.ys
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
read_verilog -sv package_import_specific.sv
|
||||
read_verilog -sv package_import_specific_module.sv
|
||||
hierarchy -check
|
||||
proc
|
||||
opt -full
|
||||
16
tests/verilog/package_import_specific_module.sv
Normal file
16
tests/verilog/package_import_specific_module.sv
Normal file
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue