diff options
-rw-r--r-- | frontends/ast/ast.cc | 38 | ||||
-rw-r--r-- | frontends/verilog/parser.y | 30 | ||||
-rw-r--r-- | frontends/verilog/verilog_frontend.cc | 8 |
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); |