aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--frontends/ast/ast.cc38
-rw-r--r--frontends/verilog/parser.y30
-rw-r--r--frontends/verilog/verilog_frontend.cc8
3 files changed, 49 insertions, 27 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 0ea38b506..d59ff1bb6 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -945,21 +945,35 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
flag_icells = icells;
flag_autowire = autowire;
+ std::vector<AstNode*> global_decls;
+
log_assert(current_ast->type == AST_DESIGN);
- for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++) {
- if (flag_icells && (*it)->str.substr(0, 2) == "\\$")
- (*it)->str = (*it)->str.substr(1);
- if (defer)
- (*it)->str = "$abstract" + (*it)->str;
- if (design->has((*it)->str)) {
- if (!ignore_redef)
- log_error("Re-definition of module `%s' at %s:%d!\n",
+ for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++)
+ {
+ if ((*it)->type == AST_MODULE)
+ {
+ for (auto n : global_decls)
+ (*it)->children.push_back(n->clone());
+
+ if (flag_icells && (*it)->str.substr(0, 2) == "\\$")
+ (*it)->str = (*it)->str.substr(1);
+
+ if (defer)
+ (*it)->str = "$abstract" + (*it)->str;
+
+ if (design->has((*it)->str)) {
+ if (!ignore_redef)
+ log_error("Re-definition of module `%s' at %s:%d!\n",
+ (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
+ log("Ignoring re-definition of module `%s' at %s:%d!\n",
(*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
- log("Ignoring re-definition of module `%s' at %s:%d!\n",
- (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
- continue;
+ continue;
+ }
+
+ design->add(process_module(*it, defer));
}
- design->add(process_module(*it, defer));
+ else
+ global_decls.push_back(*it);
}
}
diff --git a/frontends/verilog/parser.y b/frontends/verilog/parser.y
index bf9b21bb6..acd904e55 100644
--- a/frontends/verilog/parser.y
+++ b/frontends/verilog/parser.y
@@ -137,14 +137,21 @@ static void free_attr(std::map<std::string, AstNode*> *al)
%%
-input:
- module input |
- defattr input |
- /* empty */ {
- for (auto &it : default_attr_list)
- delete it.second;
- default_attr_list.clear();
- };
+input: {
+ ast_stack.push_back(current_ast);
+} design {
+ ast_stack.pop_back();
+ log_assert(SIZE(ast_stack) == 0);
+ for (auto &it : default_attr_list)
+ delete it.second;
+ default_attr_list.clear();
+};
+
+design:
+ module design |
+ defattr design |
+ task_func_decl design |
+ /* empty */;
attr:
{
@@ -214,9 +221,9 @@ module:
attr TOK_MODULE TOK_ID {
do_not_require_port_stubs = false;
AstNode *mod = new AstNode(AST_MODULE);
- current_ast->children.push_back(mod);
- current_ast_mod = mod;
+ ast_stack.back()->children.push_back(mod);
ast_stack.push_back(mod);
+ current_ast_mod = mod;
port_stubs.clear();
port_counter = 0;
mod->str = *$3;
@@ -227,7 +234,8 @@ module:
frontend_verilog_yyerror("Missing details for module port `%s'.",
port_stubs.begin()->first.c_str());
ast_stack.pop_back();
- log_assert(ast_stack.size() == 0);
+ log_assert(ast_stack.size() == 1);
+ current_ast_mod = NULL;
};
module_para_opt:
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc
index 4466e1cb6..195789086 100644
--- a/frontends/verilog/verilog_frontend.cc
+++ b/frontends/verilog/verilog_frontend.cc
@@ -285,10 +285,10 @@ struct VerilogFrontend : public Frontend {
frontend_verilog_yylex_destroy();
for (auto &child : current_ast->children) {
- log_assert(child->type == AST::AST_MODULE);
- for (auto &attr : attributes)
- if (child->attributes.count(attr) == 0)
- child->attributes[attr] = AST::AstNode::mkconst_int(1, false);
+ if (child->type == AST::AST_MODULE)
+ for (auto &attr : attributes)
+ if (child->attributes.count(attr) == 0)
+ child->attributes[attr] = AST::AstNode::mkconst_int(1, false);
}
AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_ignore_redef, flag_defer, default_nettype_wire);