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 7e4a9c8..0715106 100644
--- a/systemverilog-plugin/UhdmAst.cc
+++ b/systemverilog-plugin/UhdmAst.cc
@@ -502,6 +502,8 @@
unpacked_ranges.push_back(r->clone());
}
}
+ delete_attribute(wire_node, attr_id::packed_ranges);
+ delete_attribute(wire_node, attr_id::unpacked_ranges);
AST::AstNode *wiretype_ast = nullptr;
log_assert(AST_INTERNAL::current_scope.count(wiretype_node->str));
wiretype_ast = AST_INTERNAL::current_scope[wiretype_node->str];
@@ -518,28 +520,40 @@
wire_node->children[0]->range_left = struct_width;
wire_node->children[0]->children[0]->integer = struct_width;
}
- if (wiretype_ast && wire_node->attributes.count(ID::wiretype)) {
+ if (wiretype_ast) {
+ log_assert(wire_node->attributes.count(ID::wiretype));
log_assert(wiretype_ast->type == AST::AST_TYPEDEF);
wire_node->attributes[ID::wiretype]->id2ast = wiretype_ast->children[0];
}
if ((wire_node->children[0]->type == AST::AST_RANGE || (wire_node->children.size() > 1 && wire_node->children[1]->type == AST::AST_RANGE)) &&
wire_node->multirange_dimensions.empty()) {
+ // We need to save order in which ranges appear in wiretype and add them before wire range
+ // We need to copy this ranges, so create new vector for them
+ std::vector<AST::AstNode *> packed_ranges_wiretype;
+ std::vector<AST::AstNode *> unpacked_ranges_wiretype;
if (wiretype_ast && !wiretype_ast->children.empty() && wiretype_ast->children[0]->attributes.count(UhdmAst::packed_ranges()) &&
wiretype_ast->children[0]->attributes.count(UhdmAst::unpacked_ranges())) {
for (auto r : wiretype_ast->children[0]->attributes[UhdmAst::packed_ranges()]->children) {
- packed_ranges.push_back(r->clone());
+ packed_ranges_wiretype.push_back(r->clone());
}
for (auto r : wiretype_ast->children[0]->attributes[UhdmAst::unpacked_ranges()]->children) {
- unpacked_ranges.push_back(r->clone());
+ unpacked_ranges_wiretype.push_back(r->clone());
}
} else {
if (wire_node->children[0]->type == AST::AST_RANGE)
- packed_ranges.push_back(wire_node->children[0]->clone());
+ packed_ranges_wiretype.push_back(wire_node->children[0]->clone());
else if (wire_node->children[1]->type == AST::AST_RANGE)
- packed_ranges.push_back(wire_node->children[1]->clone());
+ packed_ranges_wiretype.push_back(wire_node->children[1]->clone());
else
log_error("Unhandled case in resolve_wiretype!\n");
}
+ // add wiretype range before current wire ranges
+ std::reverse(packed_ranges_wiretype.begin(), packed_ranges_wiretype.end());
+ std::reverse(unpacked_ranges_wiretype.begin(), unpacked_ranges_wiretype.end());
+ std::reverse(packed_ranges.begin(), packed_ranges.end());
+ std::reverse(unpacked_ranges.begin(), unpacked_ranges.end());
+ packed_ranges.insert(packed_ranges.begin(), packed_ranges_wiretype.begin(), packed_ranges_wiretype.end());
+ unpacked_ranges.insert(unpacked_ranges.begin(), unpacked_ranges_wiretype.begin(), unpacked_ranges_wiretype.end());
AST::AstNode *value = nullptr;
if (wire_node->children[0]->type != AST::AST_RANGE) {
value = wire_node->children[0]->clone();
@@ -547,26 +561,7 @@
delete_children(wire_node);
if (value)
wire_node->children.push_back(value);
- wire_node->attributes[UhdmAst::packed_ranges()] = AST::AstNode::mkconst_int(1, false, 1);
- if (!packed_ranges.empty()) {
- std::reverse(packed_ranges.begin(), packed_ranges.end());
- wire_node->attributes[UhdmAst::packed_ranges()]->children.insert(wire_node->attributes[UhdmAst::packed_ranges()]->children.end(),
- packed_ranges.begin(), packed_ranges.end());
- packed_ranges.clear();
- }
-
- wire_node->attributes[UhdmAst::unpacked_ranges()] = AST::AstNode::mkconst_int(1, false, 1);
- if (!unpacked_ranges.empty()) {
- wire_node->attributes[UhdmAst::unpacked_ranges()]->children.insert(wire_node->attributes[UhdmAst::unpacked_ranges()]->children.end(),
- unpacked_ranges.begin(), unpacked_ranges.end());
- unpacked_ranges.clear();
- }
- }
- for (auto *range : packed_ranges) {
- delete range;
- }
- for (auto *range : unpacked_ranges) {
- delete range;
+ add_multirange_wire(wire_node, packed_ranges, unpacked_ranges, false /* reverse */);
}
}
@@ -754,11 +749,6 @@
}
}
- if (wire_node->type == AST::AST_STRUCT_ITEM || wire_node->type == AST::AST_STRUCT) {
- delete_attribute(wire_node, UhdmAst::packed_ranges());
- delete_attribute(wire_node, UhdmAst::unpacked_ranges());
- }
-
// Insert new range
wire_node->children.insert(wire_node->children.end(), ranges.begin(), ranges.end());
}
@@ -1360,12 +1350,13 @@
}
break;
case AST::AST_STRUCT_ITEM:
- AST_INTERNAL::current_scope[current_node->str] = current_node;
- if (current_node->attributes.count(UhdmAst::packed_ranges()) || current_node->attributes.count(UhdmAst::unpacked_ranges())) {
+ if (!current_node->attributes.count(UhdmAst::is_simplified_wire())) {
+ current_node->attributes[UhdmAst::is_simplified_wire()] = AST::AstNode::mkconst_int(1, true);
+ AST_INTERNAL::current_scope[current_node->str] = current_node;
convert_packed_unpacked_range(current_node);
+ while (simplify(current_node, true, false, false, 1, -1, false, false)) {
+ };
}
- while (simplify(current_node, true, false, false, 1, -1, false, false)) {
- };
break;
case AST::AST_TCALL:
if (current_node->str == "$display" || current_node->str == "$write")
@@ -1850,17 +1841,15 @@
current_node->str = str;
delete node;
} else if (node) {
- current_node->str = node->str;
- if (node->type == AST::AST_ENUM && !node->children.empty()) {
- for (auto *c : node->children[0]->children) {
- if (c->type == AST::AST_RANGE && c->str.empty())
- packed_ranges.push_back(c);
- else
- delete c;
- }
- node->children[0]->children.clear();
+ if (!node->str.empty()) {
+ AST::AstNode *const wiretype_node = make_named_node(AST::AST_WIRETYPE);
+ wiretype_node->str = node->str;
+ current_node->children.push_back(wiretype_node);
+ current_node->is_custom_type = true;
+ auto it = shared.param_types.find(current_node->str);
+ if (it == shared.param_types.end())
+ shared.param_types.insert(std::make_pair(current_node->str, node->clone()));
}
- delete node;
}
});
add_multirange_wire(current_node, std::move(packed_ranges), std::move(unpacked_ranges));
@@ -2032,15 +2021,17 @@
delete type_node;
} else {
type_node->str = "$enum" + std::to_string(shared.next_enum_id());
+ std::vector<AST::AstNode *> packed_ranges;
auto wire_node = new AST::AstNode(AST::AST_WIRE);
wire_node->is_reg = true;
wire_node->attributes["\\enum_type"] = AST::AstNode::mkconst_str(type_node->str);
if (!type_node->children.empty() && type_node->children[0]->children.size() > 1) {
- wire_node->children.push_back(type_node->children[0]->children[1]->clone());
+ packed_ranges.push_back(type_node->children[0]->children[1]->clone());
} else {
// Add default range
- wire_node->children.push_back(make_range(31, 0));
+ packed_ranges.push_back(make_range(31, 0));
}
+ add_multirange_wire(wire_node, std::move(packed_ranges), {});
typedef_node->children.push_back(wire_node);
current_node->children.push_back(type_node);
current_node->children.push_back(typedef_node);
@@ -4481,6 +4472,8 @@
}
}
visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
+ if (packed_ranges.empty())
+ packed_ranges.push_back(make_range(0, 0));
add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
current_node->is_signed = vpi_get(vpiSigned, obj_h);
}
diff --git a/systemverilog-plugin/third_party/yosys/simplify.cc b/systemverilog-plugin/third_party/yosys/simplify.cc
index 0770605..cdc39b4 100644
--- a/systemverilog-plugin/third_party/yosys/simplify.cc
+++ b/systemverilog-plugin/third_party/yosys/simplify.cc
@@ -1485,7 +1485,7 @@
}
// resolve types of wires
- if (ast_node->type == Yosys::AST::AST_WIRE || ast_node->type == Yosys::AST::AST_MEMORY) {
+ if (ast_node->type == Yosys::AST::AST_WIRE || ast_node->type == Yosys::AST::AST_MEMORY || ast_node->type == Yosys::AST::AST_STRUCT_ITEM) {
if (ast_node->is_custom_type) {
log_assert(ast_node->children.size() >= 1);
log_assert(ast_node->children[0]->type == Yosys::AST::AST_WIRETYPE);