@@ -58,6 +58,7 @@ static IdString is_imported;
5858static IdString is_simplified_wire;
5959static IdString low_high_bound;
6060static IdString is_type_parameter;
61+ static IdString is_elaborated_module;
6162}; // namespace attr_id
6263
6364// TODO(mglb): use attr_id::* directly everywhere and remove those methods.
@@ -68,6 +69,9 @@ static IdString is_type_parameter;
6869/* static*/ const IdString &UhdmAst::is_imported () { return attr_id::is_imported; }
6970/* static*/ const IdString &UhdmAst::is_simplified_wire () { return attr_id::is_simplified_wire; }
7071/* static*/ const IdString &UhdmAst::low_high_bound () { return attr_id::low_high_bound; }
72+ /* static*/ const IdString &UhdmAst::is_elaborated_module () { return attr_id::is_elaborated_module; }
73+
74+ #define MAKE_INTERNAL_ID (X ) IdString(" $systemverilog_plugin$" #X)
7175
7276void attr_id_init ()
7377{
@@ -80,14 +84,15 @@ void attr_id_init()
8084
8185 // Register IdStrings. Can't be done statically, as the IdString class uses resources created during Yosys initialization which happens after
8286 // static initialization of the plugin when everything is statically linked.
83- attr_id::partial = IdString (" $systemverilog_plugin$partial" );
84- attr_id::packed_ranges = IdString (" $systemverilog_plugin$packed_ranges" );
85- attr_id::unpacked_ranges = IdString (" $systemverilog_plugin$unpacked_ranges" );
86- attr_id::force_convert = IdString (" $systemverilog_plugin$force_convert" );
87- attr_id::is_imported = IdString (" $systemverilog_plugin$is_imported" );
88- attr_id::is_simplified_wire = IdString (" $systemverilog_plugin$is_simplified_wire" );
89- attr_id::low_high_bound = IdString (" $systemverilog_plugin$low_high_bound" );
90- attr_id::is_type_parameter = IdString (" $systemverilog_plugin$is_type_parameter" );
87+ attr_id::partial = MAKE_INTERNAL_ID (partial);
88+ attr_id::packed_ranges = MAKE_INTERNAL_ID (packed_ranges);
89+ attr_id::unpacked_ranges = MAKE_INTERNAL_ID (unpacked_ranges);
90+ attr_id::force_convert = MAKE_INTERNAL_ID (force_convert);
91+ attr_id::is_imported = MAKE_INTERNAL_ID (is_imported);
92+ attr_id::is_simplified_wire = MAKE_INTERNAL_ID (is_simplified_wire);
93+ attr_id::low_high_bound = MAKE_INTERNAL_ID (low_high_bound);
94+ attr_id::is_type_parameter = MAKE_INTERNAL_ID (is_type_parameter);
95+ attr_id::is_elaborated_module = MAKE_INTERNAL_ID (is_elaborated_module);
9196}
9297
9398void attr_id_cleanup ()
@@ -101,6 +106,7 @@ void attr_id_cleanup()
101106 attr_id::packed_ranges = IdString ();
102107 attr_id::partial = IdString ();
103108 attr_id::is_type_parameter = IdString ();
109+ attr_id::is_elaborated_module = IdString ();
104110 attr_id::already_initialized = false ;
105111}
106112
@@ -143,7 +149,7 @@ static void delete_internal_attributes(AST::AstNode *node)
143149 return ;
144150
145151 for (auto &attr : {UhdmAst::partial (), UhdmAst::packed_ranges (), UhdmAst::unpacked_ranges (), UhdmAst::force_convert (), UhdmAst::is_imported (),
146- UhdmAst::is_simplified_wire (), UhdmAst::low_high_bound (), attr_id::is_type_parameter}) {
152+ UhdmAst::is_simplified_wire (), UhdmAst::low_high_bound (), attr_id::is_type_parameter, attr_id::is_elaborated_module }) {
147153 delete_attribute (node, attr);
148154 }
149155}
@@ -2185,6 +2191,8 @@ void UhdmAst::process_module()
21852191 [](auto node) { return node->type == AST::AST_INITIAL || node->type == AST::AST_ALWAYS; });
21862192 auto children_after_process = std::vector<AST::AstNode *>(process_it, current_node->children .end ());
21872193 current_node->children .erase (process_it, current_node->children .end ());
2194+ auto old_top = shared.current_top_node ;
2195+ shared.current_top_node = current_node;
21882196 visit_one_to_many ({vpiModule, vpiInterface, vpiParameter, vpiParamAssign, vpiPort, vpiNet, vpiArrayNet, vpiTaskFunc, vpiGenScopeArray,
21892197 vpiContAssign, vpiVariables},
21902198 obj_h, [&](AST::AstNode *node) {
@@ -2203,6 +2211,7 @@ void UhdmAst::process_module()
22032211 current_node->children .push_back (node);
22042212 }
22052213 });
2214+ shared.current_top_node = old_top;
22062215 current_node->children .insert (current_node->children .end (), children_after_process.begin (), children_after_process.end ());
22072216
22082217 delete_attribute (current_node, UhdmAst::partial ());
@@ -2308,6 +2317,10 @@ void UhdmAst::process_module()
23082317 module_node = module_node->clone ();
23092318 module_node->str = module_name;
23102319 }
2320+ } else if (auto attribute = get_attribute (module_node, attr_id::is_elaborated_module); attribute && attribute->integer == 1 ) {
2321+ // we already processed module with this parameters, just create cell node
2322+ make_cell (obj_h, current_node, module_node);
2323+ return ;
23112324 }
23122325 shared.top_nodes [module_node->str ] = module_node;
23132326 visit_one_to_many ({vpiParamAssign}, obj_h, [&](AST::AstNode *node) {
@@ -2350,6 +2363,7 @@ void UhdmAst::process_module()
23502363 });
23512364 make_cell (obj_h, current_node, module_node);
23522365 shared.current_top_node = old_top;
2366+ set_attribute (module_node, attr_id::is_elaborated_module, AST::AstNode::mkconst_int (1 , true ));
23532367 }
23542368}
23552369
@@ -2675,9 +2689,8 @@ void UhdmAst::process_enum_typespec()
26752689 // anonymous typespec
26762690 std::string typedef_name = " $systemverilog_plugin$anonymous_enum" + std::to_string (shared.next_anonymous_enum_typedef_id ());
26772691 current_node->str = typedef_name;
2678- auto current_scope = find_ancestor ({AST::AST_PACKAGE, AST::AST_MODULE, AST::AST_BLOCK, AST::AST_GENBLOCK});
2679- uhdmast_assert (current_scope != nullptr );
2680- move_type_to_new_typedef (current_scope, current_node);
2692+ uhdmast_assert (shared.current_top_node != nullptr );
2693+ move_type_to_new_typedef (shared.current_top_node , current_node);
26812694 current_node = make_node (AST::AST_WIRETYPE);
26822695 current_node->str = typedef_name;
26832696 shared.anonymous_enums [enum_object] = std::move (typedef_name);
0 commit comments