// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "mpact/sim/decoder/instruction_group.h"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <string>
#include <tuple>
#include <utility>

#include "absl/container/btree_map.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "antlr4-runtime/Token.h"
#include "mpact/sim/decoder/bin_encoding_info.h"
#include "mpact/sim/decoder/decoder_error_listener.h"
#include "mpact/sim/decoder/encoding_group.h"
#include "mpact/sim/decoder/extract.h"
#include "mpact/sim/decoder/format_name.h"
#include "mpact/sim/decoder/instruction_encoding.h"

namespace mpact {
namespace sim {
namespace decoder {
namespace bin_format {

using ::mpact::sim::machine_description::instruction_set::ToPascalCase;

InstructionGroup::InstructionGroup(std::string name, int width,
                                   std::string format_name,
                                   std::string opcode_enum,
                                   BinEncodingInfo* encoding_info)
    : name_(name),
      width_(width),
      format_name_(format_name),
      opcode_enum_(opcode_enum),
      encoding_info_(encoding_info) {
  format_ = encoding_info->GetFormat(format_name);
}

InstructionGroup::~InstructionGroup() {
  for (auto* enc : encoding_vec_) {
    delete enc;
  }
  encoding_map_.clear();
  encoding_vec_.clear();
  for (auto* group : encoding_group_vec_) {
    delete group;
  }
  encoding_group_vec_.clear();
}

// Add an instruction encoding into the current group. Check that the format
// 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, bool is_duplicate) {
  if ((format != nullptr) &&
      ((format_ == nullptr) || (!format->IsDerivedFrom(format_)))) {
    encoding_info_->error_listener()->semanticError(
        token, absl::StrCat("Format '", format->name(),
                            "' used by instruction encoding '", name,
                            "' is not derived from '", format_name_, "'"));
    return nullptr;
  }

  // No need to double check width, since the format at this point derives
  // from the the instruction group format.

  // 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) && !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, 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()) &&
      !encoding->is_duplicate()) {
    encoding_info_->error_listener()->semanticWarning(
        nullptr, absl::StrCat("Duplicate instruction opcode name '",
                              encoding->name(), "' in group '", name(), "'."));
  }
  encoding_name_map_.insert(std::make_pair(encoding->name(), encoding));
  encoding_vec_.push_back(encoding);
}

void InstructionGroup::ProcessEncodings() {
  if (encoding_vec_.empty()) {
    encoding_info_->error_listener()->semanticWarning(
        nullptr,
        absl::StrCat("No encodings in instruction group: '", name(), "'"));
    return;
  }
  // Insert the encodings into a map based on the mask value - grouping
  // instructions with the same mask.
  for (auto* enc : encoding_vec_) {
    encoding_map_.insert(std::make_pair(enc->GetMask(), enc));
  }
  encoding_group_vec_.push_back(new EncodingGroup(this, 0));
  for (auto& [unused, enc_ptr] : encoding_map_) {
    bool is_added = false;
    for (auto* group : encoding_group_vec_) {
      if (group->CanAddEncoding(enc_ptr)) {
        group->AddEncoding(enc_ptr);
        is_added = true;
        break;
      }
    }
    if (!is_added) {
      encoding_group_vec_.push_back(new EncodingGroup(this, 0));
      encoding_group_vec_.back()->AddEncoding(enc_ptr);
      is_added = true;
    }
  }
  for (auto* grp : encoding_group_vec_) {
    grp->AddSubGroups();
  }
}

// Check for encoding errors.
void InstructionGroup::CheckEncodings() {
  for (auto* enc_grp : encoding_group_vec_) {
    enc_grp->CheckEncodings();
  }
}

absl::Status InstructionGroup::AddSpecialization(
    const std::string& name, const std::string& parent_name,
    InstructionEncoding* encoding) {
  if (encoding_name_map_.contains(name)) {
    encoding_info_->error_listener()->semanticError(
        nullptr,
        absl::StrCat("Duplicate instruction specialization opcode name '", name,
                     "' in group '", this->name(), "'."));
    return absl::AlreadyExistsError(
        absl::StrCat("Duplicate instruction specialization opcode name '", name,
                     "' in group '", this->name(), "'."));
  }
  encoding_name_map_.insert(std::make_pair(name, encoding));
  auto* parent_encoding = encoding_name_map_.at(parent_name);
  return parent_encoding->AddSpecialization(name, encoding);
}

// Helper function used to sort the instruction group elements in a vector.
static bool InstructionGroupLess(EncodingGroup* lhs, EncodingGroup* rhs) {
  uint64_t lhs_value = 0;
  uint64_t rhs_value = 0;
  if (lhs->parent() == nullptr) {
    auto grp_recipe = GetExtractionRecipe(lhs->constant());
    lhs_value = ExtractValue(lhs->encoding_vec()[0]->GetValue(), grp_recipe);
    rhs_value = ExtractValue(rhs->encoding_vec()[0]->GetValue(), grp_recipe);
  } else {
    auto grp_recipe = GetExtractionRecipe(lhs->parent()->discriminator());
    lhs_value = ExtractValue(lhs->encoding_vec()[0]->GetValue(), grp_recipe);
    rhs_value = ExtractValue(rhs->encoding_vec()[0]->GetValue(), grp_recipe);
  }
  return lhs_value < rhs_value;
}

// Emit the code in the form of two strings that are returned in a tuple.
std::tuple<std::string, std::string> InstructionGroup::EmitDecoderCode() {
  std::string h_string;
  std::string cc_string;

  if (encoding_group_vec_.empty()) return std::make_tuple(h_string, cc_string);

  // First sort the encoding group vector according to the value of the
  // discriminator bits.
  std::sort(encoding_group_vec_.begin(), encoding_group_vec_.end(),
            &InstructionGroupLess);

  std::string initializers;
  // The signature for the top level decode function for this instruction
  // group.
  std::string signature =
      absl::StrCat(opcode_enum_, " Decode", this->name(), "(",
                   format_->uint_type_name(), " inst_word)");
  std::string w_format_signature = absl::StrCat(
      "std::pair<", opcode_enum_, ", FormatEnum> Decode", this->name(),
      "WithFormat(", format_->uint_type_name(), " inst_word)");
  // First part of the definition of the top level decoder function.
  std::string top_level_decoder = absl::StrCat(signature, " {\n");
  std::string w_format_top_level_decoder =
      absl::StrCat(w_format_signature, " {\n");
  std::string declarations =
      absl::StrCat("std::pair<", opcode_enum_, ", FormatEnum> Decode",
                   this->name(), "None(", format_->uint_type_name(), ");\n");
  std::string definitions = absl::StrCat(
      "std::pair<", opcode_enum_, ", FormatEnum> Decode", this->name(), "None(",
      format_->uint_type_name(), ") {\n  return std::make_pair(", opcode_enum_,
      "::kNone, FormatEnum::kNone);\n}\n\n");
  for (size_t i = 0; i < encoding_group_vec_.size(); i++) {
    auto* grp = encoding_group_vec_[i];
    std::string name = absl::StrCat(this->name(), "_", absl::Hex(i));
    grp->EmitInitializers(name, &initializers, opcode_enum_);
    grp->EmitDecoders(name, &declarations, &definitions, opcode_enum_);
    absl::StrAppend(&top_level_decoder, "  auto opcode = Decode", name,
                    "(inst_word).first;\n");
    absl::StrAppend(&w_format_top_level_decoder,
                    "  auto opcode_format = Decode", name, "(inst_word);\n");
    if (encoding_group_vec_.size() > 1) {
      absl::StrAppend(&top_level_decoder, "  if (opcode != ", opcode_enum_,
                      "::kNone) return opcode;\n");
      absl::StrAppend(&w_format_top_level_decoder,
                      "  if (opcode_format.first != ", opcode_enum_,
                      "::kNone) return opcode_format;\n");
    }
  }
  // Last part of the definition of the top level decoder function.
  absl::StrAppend(&top_level_decoder,
                  "  return opcode;\n"
                  "}\n");
  absl::StrAppend(&w_format_top_level_decoder,
                  "  return opcode_format;\n"
                  "}\n");
  // String the different strings together in order and return.
  absl::StrAppend(&cc_string, declarations, initializers, definitions,
                  top_level_decoder, w_format_top_level_decoder);
  absl::StrAppend(&h_string, signature, ";\n", w_format_signature, ";\n");
  return std::make_tuple(h_string, cc_string);
}

// Emit code to encode the instructions in the group.
void InstructionGroup::GetInstructionEncodings(
    absl::btree_map<std::string, std::tuple<uint64_t, int>>& encodings) {
  for (auto* enc : encoding_vec_) {
    encodings.insert(std::make_pair(ToPascalCase(enc->name()),
                                    std::make_tuple(enc->GetValue(), width())));
  }
}

// Write out instruction group information.
std::string InstructionGroup::WriteGroup() {
  std::string output;
  absl::StrAppend(&output, "\n\n// Instruction group: ", name_, "\n");
  absl::PadSpec pad;
  switch (width_ / 8) {
    case 1:
      pad = absl::PadSpec::kZeroPad2;
      break;
    case 2:
      pad = absl::PadSpec::kZeroPad4;
      break;
    case 4:
      pad = absl::PadSpec::kZeroPad8;
      break;
    case 8:
      pad = absl::PadSpec::kZeroPad16;
      break;
    default:
      pad = absl::PadSpec::kNoPad;
      break;
  }
  uint64_t common_mask = 0xffff'ffff'ffff'ffff;
  for (auto& [key, unused] : encoding_map_) {
    common_mask &= key;
  }
  absl::StrAppend(&output, "//   common bits: ", absl::Hex(common_mask, pad),
                  "\n");
  for (auto* grp : encoding_group_vec_) {
    absl::StrAppend(&output, grp->DumpGroup("", "  "));
  }
  return output;
}

}  // namespace bin_format
}  // namespace decoder
}  // namespace sim
}  // namespace mpact
