Merge pull request #507 from antmicro/kr/fix_enum_multirange
systemverilog-plugin: fix packed arrays of enums
diff --git a/systemverilog-plugin/UhdmAst.cc b/systemverilog-plugin/UhdmAst.cc
index fa72945..0715106 100644
--- a/systemverilog-plugin/UhdmAst.cc
+++ b/systemverilog-plugin/UhdmAst.cc
@@ -58,6 +58,7 @@
static IdString is_simplified_wire;
static IdString low_high_bound;
static IdString is_type_parameter;
+static IdString is_elaborated_module;
}; // namespace attr_id
// TODO(mglb): use attr_id::* directly everywhere and remove those methods.
@@ -68,6 +69,9 @@
/*static*/ const IdString &UhdmAst::is_imported() { return attr_id::is_imported; }
/*static*/ const IdString &UhdmAst::is_simplified_wire() { return attr_id::is_simplified_wire; }
/*static*/ const IdString &UhdmAst::low_high_bound() { return attr_id::low_high_bound; }
+/*static*/ const IdString &UhdmAst::is_elaborated_module() { return attr_id::is_elaborated_module; }
+
+#define MAKE_INTERNAL_ID(X) IdString("$systemverilog_plugin$" #X)
void attr_id_init()
{
@@ -80,14 +84,15 @@
// Register IdStrings. Can't be done statically, as the IdString class uses resources created during Yosys initialization which happens after
// static initialization of the plugin when everything is statically linked.
- attr_id::partial = IdString("$systemverilog_plugin$partial");
- attr_id::packed_ranges = IdString("$systemverilog_plugin$packed_ranges");
- attr_id::unpacked_ranges = IdString("$systemverilog_plugin$unpacked_ranges");
- attr_id::force_convert = IdString("$systemverilog_plugin$force_convert");
- attr_id::is_imported = IdString("$systemverilog_plugin$is_imported");
- attr_id::is_simplified_wire = IdString("$systemverilog_plugin$is_simplified_wire");
- attr_id::low_high_bound = IdString("$systemverilog_plugin$low_high_bound");
- attr_id::is_type_parameter = IdString("$systemverilog_plugin$is_type_parameter");
+ attr_id::partial = MAKE_INTERNAL_ID(partial);
+ attr_id::packed_ranges = MAKE_INTERNAL_ID(packed_ranges);
+ attr_id::unpacked_ranges = MAKE_INTERNAL_ID(unpacked_ranges);
+ attr_id::force_convert = MAKE_INTERNAL_ID(force_convert);
+ attr_id::is_imported = MAKE_INTERNAL_ID(is_imported);
+ attr_id::is_simplified_wire = MAKE_INTERNAL_ID(is_simplified_wire);
+ attr_id::low_high_bound = MAKE_INTERNAL_ID(low_high_bound);
+ attr_id::is_type_parameter = MAKE_INTERNAL_ID(is_type_parameter);
+ attr_id::is_elaborated_module = MAKE_INTERNAL_ID(is_elaborated_module);
}
void attr_id_cleanup()
@@ -101,6 +106,7 @@
attr_id::packed_ranges = IdString();
attr_id::partial = IdString();
attr_id::is_type_parameter = IdString();
+ attr_id::is_elaborated_module = IdString();
attr_id::already_initialized = false;
}
@@ -143,7 +149,7 @@
return;
for (auto &attr : {UhdmAst::partial(), UhdmAst::packed_ranges(), UhdmAst::unpacked_ranges(), UhdmAst::force_convert(), UhdmAst::is_imported(),
- UhdmAst::is_simplified_wire(), UhdmAst::low_high_bound(), attr_id::is_type_parameter}) {
+ UhdmAst::is_simplified_wire(), UhdmAst::low_high_bound(), attr_id::is_type_parameter, attr_id::is_elaborated_module}) {
delete_attribute(node, attr);
}
}
@@ -2176,6 +2182,8 @@
[](auto node) { return node->type == AST::AST_INITIAL || node->type == AST::AST_ALWAYS; });
auto children_after_process = std::vector<AST::AstNode *>(process_it, current_node->children.end());
current_node->children.erase(process_it, current_node->children.end());
+ auto old_top = shared.current_top_node;
+ shared.current_top_node = current_node;
visit_one_to_many({vpiModule, vpiInterface, vpiParameter, vpiParamAssign, vpiPort, vpiNet, vpiArrayNet, vpiTaskFunc, vpiGenScopeArray,
vpiContAssign, vpiVariables},
obj_h, [&](AST::AstNode *node) {
@@ -2194,6 +2202,7 @@
current_node->children.push_back(node);
}
});
+ shared.current_top_node = old_top;
current_node->children.insert(current_node->children.end(), children_after_process.begin(), children_after_process.end());
delete_attribute(current_node, UhdmAst::partial());
@@ -2299,6 +2308,10 @@
module_node = module_node->clone();
module_node->str = module_name;
}
+ } else if (auto attribute = get_attribute(module_node, attr_id::is_elaborated_module); attribute && attribute->integer == 1) {
+ // we already processed module with this parameters, just create cell node
+ make_cell(obj_h, current_node, module_node);
+ return;
}
shared.top_nodes[module_node->str] = module_node;
visit_one_to_many({vpiParamAssign}, obj_h, [&](AST::AstNode *node) {
@@ -2341,6 +2354,7 @@
});
make_cell(obj_h, current_node, module_node);
shared.current_top_node = old_top;
+ set_attribute(module_node, attr_id::is_elaborated_module, AST::AstNode::mkconst_int(1, true));
}
}
@@ -2666,9 +2680,8 @@
// anonymous typespec
std::string typedef_name = "$systemverilog_plugin$anonymous_enum" + std::to_string(shared.next_anonymous_enum_typedef_id());
current_node->str = typedef_name;
- auto current_scope = find_ancestor({AST::AST_PACKAGE, AST::AST_MODULE, AST::AST_BLOCK, AST::AST_GENBLOCK});
- uhdmast_assert(current_scope != nullptr);
- move_type_to_new_typedef(current_scope, current_node);
+ uhdmast_assert(shared.current_top_node != nullptr);
+ move_type_to_new_typedef(shared.current_top_node, current_node);
current_node = make_node(AST::AST_WIRETYPE);
current_node->str = typedef_name;
shared.anonymous_enums[enum_object] = std::move(typedef_name);
diff --git a/systemverilog-plugin/UhdmAst.h b/systemverilog-plugin/UhdmAst.h
index adee39c..bf2d1b5 100644
--- a/systemverilog-plugin/UhdmAst.h
+++ b/systemverilog-plugin/UhdmAst.h
@@ -201,6 +201,7 @@
static const ::Yosys::IdString &is_imported();
static const ::Yosys::IdString &is_simplified_wire();
static const ::Yosys::IdString &low_high_bound();
+ static const ::Yosys::IdString &is_elaborated_module();
};
// Utility for building AstNode trees.