Fix enum with multirange Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
diff --git a/systemverilog-plugin/UhdmAst.cc b/systemverilog-plugin/UhdmAst.cc index 06a50e3..fa72945 100644 --- a/systemverilog-plugin/UhdmAst.cc +++ b/systemverilog-plugin/UhdmAst.cc
@@ -496,6 +496,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]; @@ -512,28 +514,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(); @@ -541,26 +555,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 */); } } @@ -748,11 +743,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()); } @@ -1354,12 +1344,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") @@ -1844,17 +1835,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)); @@ -2026,15 +2015,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); @@ -4468,6 +4459,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);