// 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.

#ifndef MPACT_SIM_GENERIC_STATUS_REGISTER_H_
#define MPACT_SIM_GENERIC_STATUS_REGISTER_H_

#include <any>
#include <cstdint>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "mpact/sim/generic/data_buffer.h"
#include "mpact/sim/generic/operand_interface.h"
#include "mpact/sim/generic/state_item.h"
#include "mpact/sim/generic/state_item_base.h"

// This file declares a class that implements a generic read-only status
// register.

namespace mpact {
namespace sim {
namespace generic {

// The Status register class implements a read-only view of conditions that
// are evaluated dynamically when the register is read. Each bit is computed
// by calling a bool() function associated with each bit position in the value
// type. If the function returns true, the bit is set to 1, otherwise it is a 0.
// By default the functions are initialized to return false (i.e., set the bit
// to 0). The default functions can be overridden by calling the
// SetEvaluateFunction for individual bit positions with the appropriate
// evaluation functions (including lambdas).

template <typename T>
class StatusRegisterBase : public StateItemBase {
  static_assert(std::is_integral<T>::value, "Type must be integral");

 public:
  using Evaluate = absl::AnyInvocable<bool()>;
  // The constructor is in the protected section below. Others are deleted.
  StatusRegisterBase() = delete;
  StatusRegisterBase(const StatusRegisterBase&) = delete;
  StatusRegisterBase& operator=(const StatusRegisterBase&) = delete;

  T Read();
  T Read(T mask);

  void SetDataBuffer(DataBuffer* db) override {
    // Read only state item, so just decrement the ref count and ignore.
    db->DecRef();
  }

  void SetEvaluateFunction(int position, Evaluate eval) {
    evaluate_[position] = std::move(eval);
  }

 protected:
  // The constructor is called from StateItem<>
  StatusRegisterBase(ArchState* state, absl::string_view name,
                     const std::vector<int>& shape, int unit_size);

 private:
  std::vector<Evaluate> evaluate_;
  int size_;
};

template <typename T>
StatusRegisterBase<T>::StatusRegisterBase(ArchState* state,
                                          absl::string_view name,
                                          const std::vector<int>& shape,
                                          int unit_size)
    : StateItemBase(state, name, shape, unit_size), size_(sizeof(T) * 8) {
  // Initialize the evaluate functions to lambdas that return false.
  for (int i = 0; i < size_; i++) {
    evaluate_.push_back([]() -> bool { return false; });
  }
}

// Call the evaluation function for each bit position, starting at the high
// (msb) position.
template <typename T>
T StatusRegisterBase<T>::Read() {
  T value = 0;
  for (int i = size_ - 1; i >= 0; i--) {
    value <<= 1;
    value |= (evaluate_[i]() ? 1 : 0);
  }
  return value;
}

// Call the evaluation function only for the bits that are set in the mask,
// starting at the (msb) position.
template <typename T>
T StatusRegisterBase<T>::Read(T mask) {
  T value = 0;
  for (int i = size_ - 1; i >= 0; i--) {
    value <<= 1;
    if (mask & (static_cast<T>(1) << i)) {
      value |= (evaluate_[i]() ? 1 : 0);
    }
  }
  return value;
}

// The source operand type for StatusRegisters.
template <typename T>
class StatusRegisterSourceOperand : public SourceOperandInterface {
 public:
  // Construtor. Note, default constructor deleted.
  StatusRegisterSourceOperand(StatusRegisterBase<T>* status_reg,
                              std::string op_name)
      : status_register_(status_reg), op_name_(op_name) {}
  explicit StatusRegisterSourceOperand(StatusRegisterBase<T>* status_reg)
      : StatusRegisterSourceOperand(status_reg, status_reg->name()) {}
  StatusRegisterSourceOperand() = delete;

  // Return the value cast to the given type.
  bool AsBool(int i) override {
    return static_cast<bool>(status_register_->Read());
  }
  int8_t AsInt8(int i) override {
    return static_cast<int8_t>(status_register_->Read());
  }
  uint8_t AsUint8(int i) override {
    return static_cast<uint8_t>(status_register_->Read());
  }
  int16_t AsInt16(int i) override {
    return static_cast<int16_t>(status_register_->Read());
  }
  uint16_t AsUint16(int i) override {
    return static_cast<uint16_t>(status_register_->Read());
  }
  int32_t AsInt32(int i) override {
    return static_cast<int32_t>(status_register_->Read());
  }
  uint32_t AsUint32(int i) override {
    return static_cast<uint32_t>(status_register_->Read());
  }
  int64_t AsInt64(int i) override {
    return static_cast<int64_t>(status_register_->Read());
  }
  uint64_t AsUint64(int i) override {
    return static_cast<uint64_t>(status_register_->Read());
  }

  // Return the register object.
  std::any GetObject() const override { return std::any(status_register_); }

  // Returns the shape of the register.
  std::vector<int> shape() const override { return status_register_->shape(); }

  std::string AsString() const override { return op_name_; }

 private:
  StatusRegisterBase<T>* status_register_;
  std::string op_name_;
};

// Adding a deduction guide, so that the StatusRegisterSourceOperand can be
// used without template arguments, deducing the type from the constructor
// argument instead.
template <typename T>
StatusRegisterSourceOperand(StatusRegisterBase<T>*)
    -> StatusRegisterSourceOperand<T>;

template <typename ElementType>
using StatusRegister =
    StateItem<StatusRegisterBase<ElementType>, ElementType,
              StatusRegisterSourceOperand<ElementType>, void>;

}  // namespace generic
}  // namespace sim
}  // namespace mpact

#endif  // MPACT_SIM_GENERIC_STATUS_REGISTER_H_
