Adds RiscV Zicond instruction semantic functions and isa/bin_fmt defs. Adds capability to combine instruction groups other than in decoders in .bin_fmt files. PiperOrigin-RevId: 689844873 Change-Id: Ide0a427228fd32906597eeeca8c86a0b039584ce
diff --git a/mpact/sim/decoder/BinFormat.g4 b/mpact/sim/decoder/BinFormat.g4 index 1a4ba6a..57872d4 100644 --- a/mpact/sim/decoder/BinFormat.g4 +++ b/mpact/sim/decoder/BinFormat.g4
@@ -117,6 +117,7 @@ instruction_group_def : INSTRUCTION GROUP name=IDENT '[' number ']' ':' format=IDENT '{' instruction_def_list '}' ';'? + | INSTRUCTION GROUP name=IDENT '=' '{' group_name_list '}' ';'? ; instruction_def_list
diff --git a/mpact/sim/decoder/bin_format_contexts.h b/mpact/sim/decoder/bin_format_contexts.h index 5a97a47..8457626 100644 --- a/mpact/sim/decoder/bin_format_contexts.h +++ b/mpact/sim/decoder/bin_format_contexts.h
@@ -34,6 +34,7 @@ using FieldConstraintCtx = BinFormatParser::Field_constraintContext; using FieldDefCtx = BinFormatParser::Field_defContext; using FormatDefCtx = BinFormatParser::Format_defContext; +using GroupNameListCtx = BinFormatParser::Group_name_listContext; using IncludeFileCtx = BinFormatParser::Include_fileContext; using InstructionGroupDefCtx = BinFormatParser::Instruction_group_defContext; using InstructionDefCtx = BinFormatParser::Instruction_defContext;
diff --git a/mpact/sim/decoder/bin_format_visitor.cc b/mpact/sim/decoder/bin_format_visitor.cc index c969fbd..04d944e 100644 --- a/mpact/sim/decoder/bin_format_visitor.cc +++ b/mpact/sim/decoder/bin_format_visitor.cc
@@ -21,7 +21,6 @@ #include <istream> #include <list> #include <memory> -#include <new> #include <string> #include <utility> #include <vector> @@ -709,53 +708,63 @@ file_names_[context_file_map_.at(ctx)], ctx->start, absl::StrCat(group_name, ": illegal use of format name")); } - int width = ConvertToInt(ctx->number()); - std::string format_name = ctx->format->getText(); - auto iter = format_decl_map_.find(format_name); - if (iter == format_decl_map_.end()) { - error_listener_->semanticError( - file_names_[context_file_map_.at(ctx)], ctx->start, - absl::StrCat("Undefined format '", format_name, - "' used by instruction group '", group_name, "'")); - return nullptr; - } else { - VisitFormatDef(iter->second, encoding_info); - auto *format = encoding_info->GetFormat(format_name); - // Verify that the format width = declared width and also <= 64 bits wide. - if (format->declared_width() != width) { + // If the width is specified, this is a single instruction group with + // format definitions. + if (ctx->number() != nullptr) { + int width = ConvertToInt(ctx->number()); + std::string format_name = ctx->format->getText(); + auto iter = format_decl_map_.find(format_name); + if (iter == format_decl_map_.end()) { error_listener_->semanticError( - file_names_[context_file_map_.at(format_decl_map_.at(format_name))], - ctx->start, - absl::StrCat("Width of format '", format_name, "' (", - format->declared_width(), - ") differs from the declared width of instruction " - "group '", - group_name, "' (", width, ")")); + file_names_[context_file_map_.at(ctx)], ctx->start, + absl::StrCat("Undefined format '", format_name, + "' used by instruction group '", group_name, "'")); + return nullptr; + } else { + VisitFormatDef(iter->second, encoding_info); + auto *format = encoding_info->GetFormat(format_name); + // Verify that the format width = declared width and also <= 64 bits wide. + if (format->declared_width() != width) { + error_listener_->semanticError( + file_names_[context_file_map_.at(format_decl_map_.at(format_name))], + ctx->start, + absl::StrCat("Width of format '", format_name, "' (", + format->declared_width(), + ") differs from the declared width of instruction " + "group '", + group_name, "' (", width, ")")); + } + if (format->declared_width() > 64) { + error_listener_->semanticError( + file_names_[context_file_map_.at(format_decl_map_.at(format_name))], + ctx->start, + absl::StrCat("Instruction group '", group_name, + "': width must be <= 64 bits")); + } } - if (format->declared_width() > 64) { - error_listener_->semanticError( - file_names_[context_file_map_.at(format_decl_map_.at(format_name))], - ctx->start, - absl::StrCat("Instruction group '", group_name, - "': width must be <= 64 bits")); + auto inst_group_res = + encoding_info->AddInstructionGroup(group_name, width, format_name); + if (!inst_group_res.ok()) { + error_listener_->semanticError(file_names_[context_file_map_.at(ctx)], + ctx->start, + inst_group_res.status().message()); + return nullptr; } + // Parse the instruction encoding definitions in the instruction group. + auto *inst_group = inst_group_res.value(); + int file_index = context_file_map_.at(ctx); + for (auto *inst_def : ctx->instruction_def_list()->instruction_def()) { + context_file_map_.insert({inst_def, file_index}); + VisitInstructionDef(inst_def, inst_group); + } + return inst_group_res.value(); } - auto inst_group_res = - encoding_info->AddInstructionGroup(group_name, width, format_name); - if (!inst_group_res.ok()) { - error_listener_->semanticError(file_names_[context_file_map_.at(ctx)], - ctx->start, - inst_group_res.status().message()); - return nullptr; - } - // Parse the instruction encoding definitions in the instruction group. - auto *inst_group = inst_group_res.value(); - int file_index = context_file_map_.at(ctx); - for (auto *inst_def : ctx->instruction_def_list()->instruction_def()) { - context_file_map_.insert({inst_def, file_index}); - VisitInstructionDef(inst_def, inst_group); - } - return inst_group_res.value(); + // This is a group that combines multiple other instruction groups. + absl::flat_hash_set<std::string> group_name_set; + auto file_index = context_file_map_.at(ctx); + context_file_map_.insert({ctx->group_name_list(), file_index}); + return VisitInstructionGroupNameList(group_name, ctx->group_name_list(), + group_name_set, encoding_info); } void BinFormatVisitor::VisitInstructionDef(InstructionDefCtx *ctx, @@ -1078,6 +1087,12 @@ if ((attr_ctx->group_name() != nullptr) && (attr_ctx->group_name()->group_name_list() == nullptr)) { std::string group_name = attr_ctx->group_name()->IDENT()->getText(); + if (group_name_set.contains(group_name)) { + error_listener_->semanticError( + file_names_[context_file_map_.at(ctx)], attr_ctx->start, + absl::StrCat("Instruction group '", group_name, "' listed twice")); + continue; + } auto map_iter = encoding_info->instruction_group_map().find(group_name); InstructionGroup *inst_group = nullptr; @@ -1097,12 +1112,6 @@ continue; } } - if (group_name_set.contains(group_name)) { - error_listener_->semanticError( - file_names_[context_file_map_.at(ctx)], attr_ctx->start, - absl::StrCat("Instruction group '", group_name, "' listed twice")); - continue; - } group_name_set.insert(group_name); decoder->AddInstructionGroup(inst_group); continue; @@ -1110,98 +1119,26 @@ // If it is a parent group, process it here. if ((attr_ctx->group_name() != nullptr) && (attr_ctx->group_name()->group_name_list() != nullptr)) { - // Check each of the child groups. Visit any that haven't been visited - // yet, and make sure they all specify the same format. std::string group_name = attr_ctx->group_name()->IDENT()->getText(); if (group_name_set.contains(group_name)) { error_listener_->semanticError( file_names_[context_file_map_.at(ctx)], attr_ctx->start, - absl::StrCat("Instruction group '", group_name, - "' listed twice - ignored")); + absl::StrCat("Instruction group '", group_name, "' listed twice")); continue; } - std::vector<InstructionGroup *> child_groups; - std::string group_format_name; - // Iterate through the list of named "child" groups to combine. - for (auto *ident : attr_ctx->group_name()->group_name_list()->IDENT()) { - auto child_name = ident->getText(); - if (group_name_set.contains(child_name)) { - error_listener_->semanticError( - file_names_[context_file_map_.at(ctx)], attr_ctx->start, - absl::StrCat("Instruction group listed twice: '", child_name, - "' - ignored")); - continue; - } - InstructionGroup *child_group = nullptr; - auto map_iter = encoding_info->instruction_group_map().find(child_name); - if (map_iter != encoding_info->instruction_group_map().end()) { - child_group = map_iter->second; - bool exists = false; - for (auto const *group : child_groups) { - if (child_name == group->name()) { - exists = true; - break; - } - } - if (exists) { - error_listener_->semanticError( - file_names_[context_file_map_.at(ctx)], attr_ctx->start, - absl::StrCat("Instruction group '", child_name, - "' listed twice")); - continue; - } - } else { - // The instruction group hasn't been visited yet, so look up the - // declaration and visit it now. - auto iter = group_decl_map_.find(child_name); - if (iter != group_decl_map_.end()) { - child_group = - VisitInstructionGroupDef(iter->second, encoding_info.get()); - } - if (child_group == nullptr) { - error_listener_->semanticError( - file_names_[context_file_map_.at(ctx)], attr_ctx->start, - absl::StrCat("Instruction group '", child_name, "' not found")); - continue; - } - } - if (child_groups.empty()) { - group_format_name = child_group->format_name(); - } - // Check that the child groups all use the same instruction format. - if (group_format_name != child_group->format_name()) { - error_listener_->semanticError( - file_names_[context_file_map_.at(ctx)], attr_ctx->start, - absl::StrCat("Instruction group '", child_name, - "' must use format '", group_format_name, - ", to be merged into group '", group_name, "'")); - continue; - } - child_groups.push_back(child_group); + auto file_index = context_file_map_.at(ctx); + context_file_map_.insert( + {attr_ctx->group_name()->group_name_list(), file_index}); + auto *parent_group = VisitInstructionGroupNameList( + group_name, attr_ctx->group_name()->group_name_list(), group_name_set, + encoding_info.get()); + if (parent_group == nullptr) { + continue; } - if (child_groups.empty()) { - error_listener_->semanticError(attr_ctx->start, "No child groups"); - continue; - } - // Create the "parent" group and add all of the instructions from the - // child groups to it. - auto width = child_groups.front()->width(); - auto res = encoding_info->AddInstructionGroup(group_name, width, - group_format_name); - if (!res.ok()) { - error_listener_->semanticError(attr_ctx->start, res.status().message()); - continue; - } - auto parent_group = res.value(); - for (auto *child_group : child_groups) { - for (auto *encoding : child_group->encoding_vec()) { - parent_group->AddInstructionEncoding( - new InstructionEncoding(*encoding)); - } - } - group_name_set.insert(parent_group->name()); + group_name_set.insert(group_name); decoder->AddInstructionGroup(parent_group); + continue; } } if (group_name_set.empty()) { @@ -1210,6 +1147,78 @@ return encoding_info; } +InstructionGroup *BinFormatVisitor::VisitInstructionGroupNameList( + const std::string &group_name, GroupNameListCtx *ctx, + absl::flat_hash_set<std::string> &group_name_set, + BinEncodingInfo *encoding_info) { + std::vector<InstructionGroup *> child_groups; + std::string group_format_name; + // Iterate through the list of named "child" groups to combine. + for (auto *ident : ctx->IDENT()) { + auto child_name = ident->getText(); + if (group_name_set.contains(child_name)) { + error_listener_->semanticError( + file_names_[context_file_map_.at(ctx)], ctx->start, + absl::StrCat("Instruction group added twice: '", child_name, + "' - ignored")); + continue; + } + InstructionGroup *child_group = nullptr; + auto map_iter = encoding_info->instruction_group_map().find(child_name); + if (map_iter != encoding_info->instruction_group_map().end()) { + child_group = map_iter->second; + } else { + // The instruction group hasn't been visited yet, so look up the + // declaration and visit it now. + auto iter = group_decl_map_.find(child_name); + if (iter != group_decl_map_.end()) { + child_group = VisitInstructionGroupDef(iter->second, encoding_info); + } + if (child_group == nullptr) { + error_listener_->semanticError( + file_names_[context_file_map_.at(ctx)], ctx->start, + absl::StrCat("Instruction group '", child_name, "' not found")); + continue; + } + } + // If this is the first child group, then set the format name. + if (child_groups.empty()) { + group_format_name = child_group->format_name(); + } else if (group_format_name != child_group->format_name()) { + // Check that the child groups all use the same instruction format. + error_listener_->semanticError( + file_names_[context_file_map_.at(ctx)], ctx->start, + absl::StrCat("Instruction group '", child_name, "' must use format '", + group_format_name, ", to be merged into group '", + group_name, "'")); + continue; + } + group_name_set.insert(child_name); + child_groups.push_back(child_group); + } + + if (child_groups.empty()) { + error_listener_->semanticError(ctx->start, "No child groups"); + return nullptr; + } + // Create the "parent" group and add all of the instructions from the + // child groups to it. + auto width = child_groups.front()->width(); + auto res = + encoding_info->AddInstructionGroup(group_name, width, group_format_name); + if (!res.ok()) { + error_listener_->semanticError(ctx->start, res.status().message()); + return nullptr; + } + auto parent_group = res.value(); + for (auto *child_group : child_groups) { + for (auto *encoding : child_group->encoding_vec()) { + parent_group->AddInstructionEncoding(new InstructionEncoding(*encoding)); + } + } + return parent_group; +} + } // namespace bin_format } // namespace decoder } // namespace sim
diff --git a/mpact/sim/decoder/bin_format_visitor.h b/mpact/sim/decoder/bin_format_visitor.h index 25a99bb..cd5ae1a 100644 --- a/mpact/sim/decoder/bin_format_visitor.h +++ b/mpact/sim/decoder/bin_format_visitor.h
@@ -24,6 +24,7 @@ #include <vector> #include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" #include "antlr4-runtime/ParserRuleContext.h" @@ -126,6 +127,10 @@ const std::string &template_str_in) const; void VisitConstraint(Format *format, FieldConstraintCtx *ctx, InstructionEncoding *inst_encoding); + InstructionGroup *VisitInstructionGroupNameList( + const std::string &group_name, GroupNameListCtx *ctx, + absl::flat_hash_set<std::string> &group_name_set, + BinEncodingInfo *encoding_info); // Accessors. decoder::DecoderErrorListener *error_listener() const {
diff --git a/mpact/sim/decoder/test/bin_format_visitor_test.cc b/mpact/sim/decoder/test/bin_format_visitor_test.cc index 217b66a..4080b13 100644 --- a/mpact/sim/decoder/test/bin_format_visitor_test.cc +++ b/mpact/sim/decoder/test/bin_format_visitor_test.cc
@@ -618,13 +618,13 @@ "Error: No such instruction group: 'InstGroup'"); EXPECT_TRUE(ptr != std::string::npos); ptr = log_sink.error_log().find( - "Error: Instruction group 'inst32a' listed twice - ignored"); + "Error: Instruction group added twice: 'inst32a' - ignored"); EXPECT_TRUE(ptr != std::string::npos); ptr = log_sink.error_log().find( - "Error: Instruction group 'InstGroup2' listed twice - ignored"); + "Error: Instruction group 'InstGroup2' listed twice"); EXPECT_TRUE(ptr != std::string::npos); ptr = log_sink.error_log().find( - "Error: Instruction group 'inst32c' listed twice"); + "Error: Instruction group added twice: 'inst32c' - ignored"); EXPECT_TRUE(ptr != std::string::npos); ptr = log_sink.error_log().find("Error: Instruction group 'inst32d' not found");
diff --git a/mpact/sim/generic/register.h b/mpact/sim/generic/register.h index 91479c4..b25861b 100644 --- a/mpact/sim/generic/register.h +++ b/mpact/sim/generic/register.h
@@ -23,7 +23,6 @@ #include <any> #include <cstdint> #include <functional> -#include <map> #include <string> #include <vector> @@ -49,7 +48,7 @@ class RegisterSourceOperand : public SourceOperandInterface { public: // Constructor. Note, default constructor deleted. - RegisterSourceOperand(RegisterBase *reg, const std::string op_name); + RegisterSourceOperand(RegisterBase *reg, std::string op_name); explicit RegisterSourceOperand(RegisterBase *reg); RegisterSourceOperand() = delete;
diff --git a/mpact/sim/generic/state_item.h b/mpact/sim/generic/state_item.h index 17116cc..1df112c 100644 --- a/mpact/sim/generic/state_item.h +++ b/mpact/sim/generic/state_item.h
@@ -15,6 +15,7 @@ #ifndef MPACT_SIM_GENERIC_STATE_ITEM_H_ #define MPACT_SIM_GENERIC_STATE_ITEM_H_ +#include <cstdint> #include <string> #include <type_traits>