aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--frontends/ast/ast.cc7
-rw-r--r--passes/hierarchy/hierarchy.cc31
-rw-r--r--tests/various/hierarchy_defer.ys19
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 &para : 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