// 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_FIFO_H_
#define MPACT_SIM_GENERIC_FIFO_H_

#include <any>
#include <cstdint>
#include <deque>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "absl/strings/string_view.h"
#include "mpact/sim/generic/arch_state.h"
#include "mpact/sim/generic/component.h"
#include "mpact/sim/generic/config.h"
#include "mpact/sim/generic/data_buffer.h"
#include "mpact/sim/generic/operand_interface.h"
#include "mpact/sim/generic/program_error.h"
#include "mpact/sim/generic/state_item.h"
#include "mpact/sim/generic/state_item_base.h"

// Contains the basic generic definitions for classes used to model
// fifo state in simulated architectures. Fifos can contain scalar,
// one-dimensional vector, or two-dimensional array values.

namespace mpact {
namespace sim {
namespace generic {

class FifoBase;

template <typename T, typename Enable = void>
class FifoSourceOperand : public SourceOperandInterface {
 public:
  // Constructor. Note, default constructor deleted.
  explicit FifoSourceOperand(FifoBase *fifo);
  FifoSourceOperand(FifoBase *fifo, const std::string op_name);
  FifoSourceOperand() = delete;

  // These accessor methods are defined to satisfy the interface. However,
  // in many cases, the purpose of the fifo is only to hold the underlying
  // DataBuffer instance, until popped in its entirety. It is therefore
  // expected that these accessors will not be used much.
  // Accessor methods call into the fifo_ data_buffer to obtain the values.
  // The index is in one dimension. For scalar registers it should always be
  // zero, for vector registers it is the element index. For higher order
  // register shapes it should be the linearized row-major order index.
  bool AsBool(int i) override;
  int8_t AsInt8(int i) override;
  uint8_t AsUint8(int i) override;
  int16_t AsInt16(int i) override;
  uint16_t AsUint16(int i) override;
  int32_t AsInt32(int i) override;
  uint32_t AsUint32(int i) override;
  int64_t AsInt64(int i) override;
  uint64_t AsUint64(int i) override;

  // Returns the FifoBase object wrapped in absl::any.
  std::any GetObject() const override { return std::any(fifo_); }

  // Returns the shape of the fifo elements.
  std::vector<int> shape() const override;

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

 private:
  FifoBase *fifo_;
  std::string op_name_;
};

// Fifo destination operand type with element value type T. It is agnostic
// of the actual structure of the underlying fifo element (scalar, vector,
// matrix).
template <typename T>
class FifoDestinationOperand : public DestinationOperandInterface {
 public:
  // Constructors
  FifoDestinationOperand(FifoBase *fifo, int latency, std::string op_name);
  FifoDestinationOperand(FifoBase *fifo, int latency);
  FifoDestinationOperand() = delete;

  // Initializes the DataBuffer instance so that when Submit is called, it can
  // be entered into the correct delay line, with the correct latency, targeting
  // the correct fifo.
  void InitializeDataBuffer(DataBuffer *db) override;

  // Since a fifo stores multiple values, this method will return a nullptr
  // as it does not make sense to copy the value from a fifo into a destination
  // DataBuffer instance that is destined for that fifo.
  DataBuffer *CopyDataBuffer() override { return nullptr; }

  // Allocates and returns an initialized DataBuffer instance.
  DataBuffer *AllocateDataBuffer() override;

  // Returns the FifoBase object wrapped in absl::any.
  std::any GetObject() const override { return std::any(fifo_); }

  // Returns the latency associated with writes to this fifo operand.
  int latency() const override { return latency_; }

  // Returns the shape of the underlying fifo element (the number of elements in
  // each dimension). For instance {0} indicates a scalar quantity, whereas
  // {128} indicates an 128 element vector quantity.
  std::vector<int> shape() const override;

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

 private:
  FifoBase *fifo_;
  DataBufferFactory *db_factory_;
  int latency_;
  DataBufferDelayLine *delay_line_;
  std::string op_name_;
};

// Base class for fifo types. Implements DataBufferInterface that
// the base class StateItemBase does not.
// The Fifo class supports the ability to reserve slots in the fifo for future
// pushes of data. The reserved slots are counted for the purpose of determining
// IsFull() or IsEmpty(), but are not counted in the number of Available()
// elements. The use of the reservation capability is not required to push data,
// but is implemented to provide modeling support for architectures where the
// allocation of fifo slots are separated from the actual push of data.
// No default constructor - should only be constructed from the derived classes.
class FifoBase : public StateItemBase, public Component {
  // Only constructed from derived classes.
 protected:
  FifoBase(class ArchState *arch_state, absl::string_view name,
           const std::vector<int> &shape, int element_size,
           int default_capacity);
  FifoBase() = delete;
  FifoBase(const FifoBase &) = delete;

 public:
  ~FifoBase() override;

 public:
  // Pushes the DataBuffer to the fifo provided there is space available.
  void SetDataBuffer(DataBuffer *db) override;

  // Returns true if the count of reserved and full slots equals or exceeds
  // fifo capacity.
  virtual bool IsFull() const;

  // Returns true if the fifo is empty and has zero slots reserved.
  virtual bool IsEmpty() const;

  // Returns true if the sum of reserved and full slots exceeds fifo capacity.
  // The fifo will not accept pushes once full, so the overflow can only only
  // be true if there are reserved slots.
  virtual bool IsOverSubscribed() const;

  // Reserves count slots in the fifo for future pushes. There is no check on
  // whether this causes overflow. This allows for a Reserve to be performed in
  // "parallel" with a Pop() without causing an error. If needed, an overflow
  // check should be performed at the end of the simulated cycle.
  virtual void Reserve(int count);

  // Pushes a value into the fifo, returns true if successful. Reference count
  // of the DataBuffer is incremented as part of Push. If the reserved count
  // is greater than zero it will decrement the reserved count. If the push
  // would overflow the fifo it returns false, and raises the overflow program
  // error if set.
  virtual bool Push(DataBuffer *db);

  // Returns a pointer to the DataBuffer at the front of the fifo. If the fifo
  // is empty, the nullptr is returned and the underflow program error, if set,
  // is raised.
  DataBuffer *Front() const;

  // Removes the front element of the fifo and decrements its reference count.
  // If the fifo is empty, the underflow program error, if set, is raised.
  virtual void Pop();

  // Returns max depth of fifo.
  unsigned Capacity() const { return capacity_; }

  // Returns the number of elements currently held in the fifo.
  unsigned Available() const;

  // Returns the number of reserved slots.
  unsigned Reserved() const { return reserved_; }

  // Setters for ProgramErrors
  void SetOverflowProgramError(std::unique_ptr<ProgramError> *program_error) {
    overflow_program_error_ = std::move(*program_error);
  }

  void SetUnderflowProgramError(std::unique_ptr<ProgramError> *program_error) {
    underflow_program_error_ = std::move(*program_error);
  }

 protected:
  // Configuration import.
  absl::Status ImportSelf(
      const mpact::sim::proto::ComponentData &component_data) override;

  ProgramError *overflow_program_error() {
    return overflow_program_error_.get();
  }
  ProgramError *underflow_program_error() {
    return underflow_program_error_.get();
  }

 private:
  Config<uint64_t> depth_;
  std::unique_ptr<ProgramError> overflow_program_error_;
  std::unique_ptr<ProgramError> underflow_program_error_;
  std::string name_;
  unsigned capacity_;
  unsigned reserved_;
  std::deque<DataBuffer *> fifo_;
};

// Scalar valued fifo with value type ElementType.
template <typename ElementType>
using Fifo = StateItem<FifoBase, ElementType, FifoSourceOperand<ElementType>,
                       FifoDestinationOperand<ElementType>>;

// Fifo of N long vectors with element value type ElementType.
template <typename ElementType, int N>
using VectorFifo =
    StateItem<FifoBase, ElementType, FifoSourceOperand<ElementType>,
              FifoDestinationOperand<ElementType>, N>;

// Fifo of MxN sized matrices with element value type ElementType.
template <typename ElementType, int M, int N>
using MatrixFifo =
    StateItem<FifoBase, ElementType, FifoSourceOperand<ElementType>,
              FifoDestinationOperand<ElementType>, M, N>;

template <typename T, typename Enable>
std::vector<int> FifoSourceOperand<T, Enable>::shape() const {
  return fifo_->shape();
}

// Helper templates for the partial specialiations below.
template <typename T>
using EnableIfIntegral =
    typename std::enable_if<std::is_integral<T>::value, void>::type;

template <typename T>
using EnableIfNotIntegral =
    typename std::enable_if<!std::is_integral<T>::value, void>::type;

// Helper function used in the partial specialization below.
template <typename F, typename T>
inline T HelperAs(const FifoBase *fifo, int i) {
  DataBuffer *db = fifo->Front();
  if (nullptr == db) {
    return static_cast<T>(0);
  }
  return static_cast<T>(db->Get<F>(i));
}

template <typename T, typename Enable>
FifoSourceOperand<T, Enable>::FifoSourceOperand(FifoBase *fifo,
                                                const std::string op_name)
    : fifo_(fifo), op_name_(op_name) {}

template <typename T, typename Enable>
FifoSourceOperand<T, Enable>::FifoSourceOperand(FifoBase *fifo)
    : FifoSourceOperand(fifo, fifo->name()) {}

template <typename T>
class FifoSourceOperand<T, EnableIfIntegral<T>>
    : public SourceOperandInterface {
 public:
  // Constructors. Note, default constructor deleted.
  FifoSourceOperand(FifoBase *fifo, const std::string op_name)
      : fifo_(fifo), op_name_(op_name) {}
  explicit FifoSourceOperand(FifoBase *fifo)
      : FifoSourceOperand(fifo, fifo->name()) {}
  FifoSourceOperand() = delete;

  // These accessor methods are defined to satisfy the interface. However,
  // in many cases, the purpose of the fifo is only to hold the underlying
  // DataBuffer instance, until popped in its entirety. It is therefore
  // expected that these accessors will not be used much.
  // Accessor methods call into the fifo_ data_buffer to obtain the values.
  // The index is in one dimension. For scalar registers it should always be
  // zero, for vector registers it is the element index. For higher order
  // register shapes it should be the linearized row-major order index.
  bool AsBool(int i) override { return HelperAs<T, bool>(fifo_, i); }
  int8_t AsInt8(int i) override { return HelperAs<T, int8_t>(fifo_, i); }
  uint8_t AsUint8(int i) override { return HelperAs<T, uint8_t>(fifo_, i); }
  int16_t AsInt16(int i) override { return HelperAs<T, int16_t>(fifo_, i); }
  uint16_t AsUint16(int i) override { return HelperAs<T, uint16_t>(fifo_, i); }
  int32_t AsInt32(int i) override { return HelperAs<T, int32_t>(fifo_, i); }
  uint32_t AsUint32(int i) override { return HelperAs<T, uint32_t>(fifo_, i); }
  int64_t AsInt64(int i) override { return HelperAs<T, int64_t>(fifo_, i); }
  uint64_t AsUint64(int i) override { return HelperAs<T, uint64_t>(fifo_, i); }

  // Returns the FifoBase object wrapped in absl::any.
  std::any GetObject() const override { return std::any(fifo_); }

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

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

 private:
  FifoBase *fifo_;
  std::string op_name_;
};

// This is a parial specialization of the Source operand class. This is used
// when the element type stored in the data buffer is not an integral type. This
// is primarily for when the fifo element type really doesn't model a register
// value per se, but a more complex structure such as a dma descriptor. In this
// case, the value interface is not intended to be used, but instead the fifo
// is accessed by using the GetObject and casting it to the appropriate type in
// order to access the source element.
template <typename T>
class FifoSourceOperand<T, EnableIfNotIntegral<T>>
    : public SourceOperandInterface {
 public:
  // Constructors. Note, default constructor deleted.
  FifoSourceOperand(FifoBase *fifo, const std::string op_name)
      : fifo_(fifo), op_name_(op_name) {}
  explicit FifoSourceOperand(FifoBase *fifo)
      : FifoSourceOperand(fifo, fifo->name()) {}
  FifoSourceOperand() = delete;

  // These accessor methods are defined to satisfy the interface.
  bool AsBool(int) override { return false; }
  int8_t AsInt8(int i) override { return 0; }
  uint8_t AsUint8(int i) override { return 0; }
  int16_t AsInt16(int i) override { return 0; }
  uint16_t AsUint16(int i) override { return 0; }
  int32_t AsInt32(int i) override { return 0; }
  uint32_t AsUint32(int i) override { return 0; }
  int64_t AsInt64(int i) override { return 0; }
  uint64_t AsUint64(int i) override { return 0; }

  std::string AsString() const override { return fifo_->name(); }

  // Returns the FifoBase object wrapped in absl::any.
  std::any GetObject() const override { return std::any(fifo_); }

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

 private:
  FifoBase *fifo_;
  std::string op_name_;
};

template <typename T>
FifoDestinationOperand<T>::FifoDestinationOperand(FifoBase *fifo, int latency,
                                                  std::string op_name)
    : fifo_(fifo),
      db_factory_(fifo->arch_state()->db_factory()),
      latency_(latency),
      delay_line_(fifo->arch_state()->data_buffer_delay_line()),
      op_name_(op_name) {}

template <typename T>
FifoDestinationOperand<T>::FifoDestinationOperand(FifoBase *fifo, int latency)
    : FifoDestinationOperand(fifo, latency, fifo->name()) {}

template <typename T>
void FifoDestinationOperand<T>::InitializeDataBuffer(DataBuffer *db) {
  db->set_destination(fifo_);
  db->set_latency(latency_);
  db->set_delay_line(delay_line_);
}

template <typename T>
DataBuffer *FifoDestinationOperand<T>::AllocateDataBuffer() {
  DataBuffer *db = db_factory_->Allocate(fifo_->size());
  InitializeDataBuffer(db);
  return db;
}

template <typename T>
std::vector<int> FifoDestinationOperand<T>::shape() const {
  return fifo_->shape();
}

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

#endif  // MPACT_SIM_GENERIC_FIFO_H_
