diff options
-rw-r--r-- | frontends/ast/ast.cc | 7 | ||||
-rw-r--r-- | passes/hierarchy/hierarchy.cc | 31 | ||||
-rw-r--r-- | tests/various/hierarchy_defer.ys | 19 |
3 files changed, 57 insertions, 0 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 82283fb5b..a3a78e414 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1099,6 +1099,13 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast ignoreThisSignalsInInitial = RTLIL::SigSpec(); } + else { + for (auto &attr : ast->attributes) { + if (attr.second->type != AST_CONSTANT) + continue; + current_module->attributes[attr.first] = attr.second->asAttrConst(); + } + } if (ast->type == AST_INTERFACE) current_module->set_bool_attribute("\\is_interface"); diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index fd95b94b2..ad795c69f 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -808,6 +808,37 @@ struct HierarchyPass : public Pass { if (mod_it.second->get_bool_attribute("\\top")) top_mod = mod_it.second; + if (top_mod != nullptr && auto_top_mode) { + IdString abstract_id = top_mod->name; + IdString top_name = abstract_id; + if (top_name.begins_with("$abstract")) + top_name = top_name.substr(strlen("$abstract")); + top_mod = design->module(top_name); + + dict<RTLIL::IdString, RTLIL::Const> top_parameters; + for (auto ¶ : parameters) { + SigSpec sig_value; + if (!RTLIL::SigSpec::parse(sig_value, NULL, para.second)) + log_cmd_error("Can't decode value '%s'!\n", para.second.c_str()); + top_parameters[RTLIL::escape_id(para.first)] = sig_value.as_const(); + } + + if (top_mod == nullptr && design->module(abstract_id)) + top_mod = design->module(design->module(abstract_id)->derive(design, top_parameters)); + else if (top_mod != nullptr && !top_parameters.empty()) + top_mod = design->module(top_mod->derive(design, top_parameters)); + + if (top_mod != nullptr && top_mod->name != top_name) { + Module *m = top_mod->clone(); + m->name = top_name; + Module *old_mod = design->module(top_name); + if (old_mod) + design->remove(old_mod); + design->add(m); + top_mod = m; + } + } + if (top_mod == nullptr && auto_top_mode) { log_header(design, "Finding top of design hierarchy..\n"); dict<Module*, int> db; diff --git a/tests/various/hierarchy_defer.ys b/tests/various/hierarchy_defer.ys new file mode 100644 index 000000000..0bf4de44e --- /dev/null +++ b/tests/various/hierarchy_defer.ys @@ -0,0 +1,19 @@ +read -vlog2k <<EOT +module first; +endmodule + +(* top *) +module top(input i, output o); +sub s0(i, o); +endmodule + +(* constant_expression=1+1?2*2:3/3 *) +module sub(input i, output o); +assign o = ~i; +endmodule +EOT + +hierarchy -auto-top +select -assert-any top +select -assert-any sub +select -assert-none foo |