No public description

PiperOrigin-RevId: 875775834
Change-Id: Ia70363c8696757c613d3cd0ed7a844c3a68d4890
diff --git a/mpact/sim/decoder/BinFormat.g4 b/mpact/sim/decoder/BinFormat.g4
index 17d6480..af4437d 100644
--- a/mpact/sim/decoder/BinFormat.g4
+++ b/mpact/sim/decoder/BinFormat.g4
@@ -141,12 +141,15 @@
 // An instruction encoding contains a name, the format it refers to, and a list
 // of binary field constraints.
 instruction_def
-  : name=IDENT ':' format_name=IDENT ':' field_constraint_list ';'
+  : duplicate? name=IDENT ':' format_name=IDENT ':' field_constraint_list ';'
   | generate=GENERATE '(' range_assignment (',' range_assignment)* ')'
     '{' generator_instruction_def_list '}' ';'
   | name=IDENT ':' SPECIALIZES parent=IDENT ':' field_constraint_list ';'
   ;
 
+duplicate
+  : '!'
+  ;
 
 range_assignment
   : IDENT '=' '[' gen_value (',' gen_value)* ']'
diff --git a/mpact/sim/decoder/bin_format_visitor.cc b/mpact/sim/decoder/bin_format_visitor.cc
index 0dbd7c5..03729b6 100644
--- a/mpact/sim/decoder/bin_format_visitor.cc
+++ b/mpact/sim/decoder/bin_format_visitor.cc
@@ -1044,8 +1044,9 @@
             ") differs from the declared width of the instruction group (",
             inst_group->width(), ")"));
   }
-  auto* inst_encoding =
-      inst_group->AddInstructionEncoding(ctx->format_name, name, format);
+  bool is_duplicate = ctx->duplicate() != nullptr;
+  auto* inst_encoding = inst_group->AddInstructionEncoding(
+      ctx->format_name, name, format, is_duplicate);
   if (format == nullptr) return;
   // Add constraints to the instruction encoding.
   for (auto* constraint : ctx->field_constraint_list()->field_constraint()) {
@@ -1467,7 +1468,8 @@
       if (iter != grp_ptr->encoding_name_map().end()) {
         auto* parent_encoding = iter->second;
         auto* format = parent_encoding->format();
-        auto* inst_encoding = new InstructionEncoding(name, format);
+        auto* inst_encoding =
+            new InstructionEncoding(name, format, /*is_duplicate=*/false);
         for (auto* constraint :
              ctx->field_constraint_list()->field_constraint()) {
           context_file_map_.insert({constraint, file_index});
diff --git a/mpact/sim/decoder/instruction_encoding.cc b/mpact/sim/decoder/instruction_encoding.cc
index c57afa9..4940273 100644
--- a/mpact/sim/decoder/instruction_encoding.cc
+++ b/mpact/sim/decoder/instruction_encoding.cc
@@ -29,8 +29,9 @@
 namespace decoder {
 namespace bin_format {
 
-InstructionEncoding::InstructionEncoding(std::string name, Format* format)
-    : name_(name), format_(format) {
+InstructionEncoding::InstructionEncoding(std::string name, Format* format,
+                                         bool is_duplicate)
+    : name_(name), format_(format), is_duplicate_(is_duplicate) {
   if (format) format_name_ = format->name();
 }
 
@@ -43,7 +44,8 @@
       mask_(encoding.mask_),
       other_mask_(encoding.other_mask_),
       extracted_mask_(encoding.extracted_mask_),
-      value_(encoding.value_) {
+      value_(encoding.value_),
+      is_duplicate_(encoding.is_duplicate_) {
   // Copy construct each of the constraints.
   for (auto* constraint : encoding.equal_constraints_) {
     equal_constraints_.push_back(new Constraint(*constraint));
diff --git a/mpact/sim/decoder/instruction_encoding.h b/mpact/sim/decoder/instruction_encoding.h
index 4dcda6e..2ee7079 100644
--- a/mpact/sim/decoder/instruction_encoding.h
+++ b/mpact/sim/decoder/instruction_encoding.h
@@ -50,7 +50,7 @@
  public:
   // Disable default constructor and assignment operator.
   InstructionEncoding() = delete;
-  InstructionEncoding(std::string name, Format* format);
+  InstructionEncoding(std::string name, Format* format, bool is_duplicate);
   InstructionEncoding(const InstructionEncoding& encoding);
   InstructionEncoding& operator=(const InstructionEncoding&) = delete;
   ~InstructionEncoding();
@@ -111,6 +111,9 @@
 
   Format* format() const { return format_; }
 
+  void set_is_duplicate(bool is_duplicate) { is_duplicate_ = is_duplicate; }
+  bool is_duplicate() const { return is_duplicate_; }
+
  private:
   // Internal helper to create and check a constraint.
   absl::StatusOr<Constraint*> CreateConstraint(ConstraintType type,
@@ -135,6 +138,10 @@
   uint64_t extracted_mask_ = 0;
   uint64_t value_ = 0;
   absl::btree_map<std::string, InstructionEncoding*> specializations_;
+  // True if this encoding is declared as using a duplicate of another opcode
+  // name. This is used to suppress warning messages for encodings which
+  // purposefully have the same opcode name as another encoding.
+  bool is_duplicate_ = false;
 };
 
 }  // namespace bin_format
diff --git a/mpact/sim/decoder/instruction_group.cc b/mpact/sim/decoder/instruction_group.cc
index 294a5da..e3684ea 100644
--- a/mpact/sim/decoder/instruction_group.cc
+++ b/mpact/sim/decoder/instruction_group.cc
@@ -67,7 +67,7 @@
 // has the correct width, and that the format the encoding is defined in, or
 // derives from the format associated with the instruction group.
 InstructionEncoding* InstructionGroup::AddInstructionEncoding(
-    antlr4::Token* token, std::string name, Format* format) {
+    antlr4::Token* token, std::string name, Format* format, bool is_duplicate) {
   if ((format != nullptr) &&
       ((format_ == nullptr) || (!format->IsDerivedFrom(format_)))) {
     encoding_info_->error_listener()->semanticError(
@@ -83,19 +83,20 @@
   // Warn if the instruction name has been seen before. It might be fully valid
   // that an instruction name has multiple encodings, but warn about it, in
   // case it is an error.
-  if (encoding_name_map_.contains(name)) {
+  if (encoding_name_map_.contains(name) && !is_duplicate) {
     encoding_info_->error_listener()->semanticWarning(
         token, absl::StrCat("Duplicate instruction opcode name '", name,
                             "' in group '", this->name(), "'."));
   }
-  auto* encoding = new InstructionEncoding(name, format);
+  auto* encoding = new InstructionEncoding(name, format, is_duplicate);
   encoding_vec_.push_back(encoding);
   encoding_name_map_.insert(std::make_pair(name, encoding));
   return encoding;
 }
 
 void InstructionGroup::AddInstructionEncoding(InstructionEncoding* encoding) {
-  if (encoding_name_map_.contains(encoding->name())) {
+  if (encoding_name_map_.contains(encoding->name()) &&
+      !encoding->is_duplicate()) {
     encoding_info_->error_listener()->semanticWarning(
         nullptr, absl::StrCat("Duplicate instruction opcode name '",
                               encoding->name(), "' in group '", name(), "'."));
diff --git a/mpact/sim/decoder/instruction_group.h b/mpact/sim/decoder/instruction_group.h
index 943c1f5..e7a7f46 100644
--- a/mpact/sim/decoder/instruction_group.h
+++ b/mpact/sim/decoder/instruction_group.h
@@ -47,7 +47,8 @@
   ~InstructionGroup();
 
   InstructionEncoding* AddInstructionEncoding(antlr4::Token* token,
-                                              std::string name, Format* format);
+                                              std::string name, Format* format,
+                                              bool is_duplicate = false);
   void AddInstructionEncoding(InstructionEncoding* encoding);
   // Process the encodings in the group, partitioning them into subgroups
   // according to their opcode bits to make it easy to generate a hierarchical
diff --git a/mpact/sim/decoder/test/instruction_encoding_test.cc b/mpact/sim/decoder/test/instruction_encoding_test.cc
index 42d935c..3380314 100644
--- a/mpact/sim/decoder/test/instruction_encoding_test.cc
+++ b/mpact/sim/decoder/test/instruction_encoding_test.cc
@@ -60,7 +60,8 @@
     (void)overlay->AddFieldReference("rs1");
     (void)overlay->AddFieldReference("rd");
     (void)i_type_fmt_->ComputeAndCheckFormatWidth();
-    i_type_ = new InstructionEncoding(kITypeEncodingName, i_type_fmt_);
+    i_type_ = new InstructionEncoding(kITypeEncodingName, i_type_fmt_,
+                                      /*is_duplicate*/ false);
     (void)i_type_fmt_->AddFieldOverlay("extract", /*is_signed*/ false, 12);
     overlay = i_type_fmt_->GetOverlay("extract");
     (void)overlay->AddFieldReference("rs1");